-
-
Save dicethedev/f1d042bcbf41dc832b484501aed44eb7 to your computer and use it in GitHub Desktop.
ERC20 Permit OpenZeppelin Tutorial - https://www.youtube.com/watch?v=lFKcga4Y6Ys
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<title>ERC20 Permit</title> | |
<script src="https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/index.min.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/@walletconnect/[email protected]/dist/umd/index.min.js"></script> | |
<script src="https://bundle.run/[email protected]"></script> | |
</head> | |
<body> | |
<script type="text/javascript"> | |
window.Buffer = buffer.Buffer // getting this from buffer module for frontend. | |
const domainName = "MyToken" // put your token name | |
const domainVersion = "1" // leave this to "1" | |
const chainId = 1 // this is for the chain's ID. value is 1 for remix | |
const contractAddress = "0xd9145CCE52D386f254917e481eB44e9943F39138" // Put the address here from remix | |
var account = null; | |
const domain = { | |
name: domainName, | |
version: domainVersion, | |
verifyingContract: contractAddress, | |
chainId | |
} | |
const domainType = [ | |
{ name: 'name', type: 'string' }, | |
{ name: 'version', type: 'string' }, | |
{ name: 'chainId', type: 'uint256' }, | |
{ name: 'verifyingContract', type: 'address' }, | |
] | |
const connect = async () => { | |
// This helps connect webpage to wallet. | |
const providerOptions = { | |
walletconnect: { | |
package: WalletConnectProvider.default, // required | |
options: { | |
rpc: { | |
1: "https://cloudflare-eth.com", | |
137: "https://polygon-rpc.com", | |
// ... | |
}, | |
} | |
} | |
}; | |
const Web3Modal = window.Web3Modal.default; | |
const web3Modal = new Web3Modal({ | |
network: "mainnet", // optional | |
cacheProvider: false, // optional | |
providerOptions, // required | |
theme: "dark" | |
}); | |
const provider = await web3Modal.connect(); | |
window.web3 = new Web3(provider); | |
var accounts = await web3.eth.getAccounts(); | |
account = accounts[0]; | |
} | |
const splitSig = (sig) => { | |
// splits the signature to r, s, and v values. | |
const pureSig = sig.replace("0x", "") | |
const r = new Buffer(pureSig.substring(0, 64), 'hex') | |
const s = new Buffer(pureSig.substring(64, 128), 'hex') | |
const v = new Buffer((parseInt(pureSig.substring(128, 130), 16)).toString()); | |
return { | |
r, s, v | |
} | |
} | |
const signTyped = (dataToSign) => { | |
// call this method to sign EIP 712 data | |
return new Promise((resolve, reject) => { | |
web3.currentProvider.sendAsync({ | |
method: "eth_signTypedData_v4", | |
params: [account, dataToSign], | |
from: account | |
}, (err, result) => { | |
if (err) return reject(err); | |
resolve(result.result) | |
}) | |
}) | |
} | |
async function createPermit(spender, value, nonce, deadline) { | |
const permit = { owner: account, spender, value, nonce, deadline } | |
const Permit = [ | |
{ name: "owner", type: "address" }, | |
{ name: "spender", type: "address" }, | |
{ name: "value", type: "uint256" }, | |
{ name: "nonce", type: "uint256" }, | |
{ name: "deadline", type: "uint256" }, | |
] | |
const dataToSign = JSON.stringify({ | |
types: { | |
EIP712Domain: domainType, | |
Permit: Permit | |
}, | |
domain: domain, | |
primaryType: "Permit", | |
message: permit | |
}); | |
const signature = await signTyped(dataToSign) | |
const split = splitSig(signature) | |
return { | |
...split, signature | |
} | |
} | |
async function main() { | |
await connect() | |
const permit = await createPermit("0x5B38Da6a701c568545dCfcB03FcB875f56beddC4", 1000, 1, 2661766724) | |
console.log(`r: 0x${permit.r.toString('hex')}, s: 0x${permit.s.toString('hex')}, v: ${permit.v}, sig: ${permit.signature}`) | |
} | |
</script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: MIT | |
pragma solidity ^0.8.4; | |
import "@openzeppelin/[email protected]/token/ERC20/ERC20.sol"; | |
import "@openzeppelin/[email protected]/token/ERC20/extensions/draft-ERC20Permit.sol"; | |
contract MyToken is ERC20, ERC20Permit { | |
constructor() ERC20("MyToken", "MTK") ERC20Permit("MyToken") {} | |
function mint(address to, uint256 value) external { | |
_mint(to, value); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment