Skip to content

Commit

Permalink
Merge pull request #8 from faranak-cs/main
Browse files Browse the repository at this point in the history
Add contracts
  • Loading branch information
faranak-cs authored Mar 2, 2024
2 parents 7c1cbac + 466f32c commit b93f1a5
Show file tree
Hide file tree
Showing 8 changed files with 184 additions and 1 deletion.
36 changes: 36 additions & 0 deletions contracts/IERC20Permit.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

interface IERC20Permit {
function totalSupply() external view returns (uint);

function balanceOf(address account) external view returns (uint);

function transfer(address recipient, uint amount) external returns (bool);

function allowance(
address owner,
address spender
) external view returns (uint);

function approve(address spender, uint amount) external returns (bool);

function transferFrom(
address sender,
address recipient,
uint amount
) external returns (bool);

function permit(
address owner,
address spender,
uint value,
uint deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;

event Transfer(address indexed from, address indexed to, uint value);
event Approval(address indexed owner, address indexed spender, uint value);
}
13 changes: 13 additions & 0 deletions contracts/OurToken.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract OurToken is ERC20, ERC20Permit {
constructor() ERC20("OurToken", "OT") ERC20Permit("OurToken") {}

function mint(address _to, uint _amount) external {
_mint(_to, _amount);
}
}
29 changes: 29 additions & 0 deletions contracts/Vault.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import "./IERC20Permit.sol";

contract Vault {
IERC20Permit public immutable token;

constructor(address _token) {
token = IERC20Permit(_token);
}

// transfer funds by executing transaction
function deposit(uint amount) external {
token.transferFrom(msg.sender, address(this), amount);
}

// transfer funds by using digital signature
function depositWithPermit(
uint amount,
uint deadline,
uint8 v,
bytes32 r,
bytes32 s
) external {
token.permit(msg.sender, address(this), amount, deadline, v, r, s);
token.transferFrom(msg.sender, address(this), amount);
}
}
2 changes: 1 addition & 1 deletion contracts/VerifySignature.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8;
pragma solidity ^0.8.24;

contract VerifySignature {
function getMessageHash(
Expand Down
7 changes: 7 additions & 0 deletions hardhat.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,12 @@ require("@nomicfoundation/hardhat-toolbox");

/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
defaultNetwork: "hardhat",
networks: {
localhost: {
url: "http://127.0.0.1:8545",
chainId: 31337,
},
},
solidity: "0.8.24",
};
7 changes: 7 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"license": "ISC",
"devDependencies": {
"@nomicfoundation/hardhat-toolbox": "^4.0.0",
"@openzeppelin/contracts": "^5.0.1",
"hardhat": "^2.20.1"
},
"dependencies": {
Expand Down
90 changes: 90 additions & 0 deletions test/erc20-permit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
const { expect } = require("chai");
const { ethers } = require("hardhat");

async function getPermitSignature(signer, token, spender, value, deadline) {
const [nonce, name, version, chainId] = await Promise.all([
token.nonces(signer.address),
token.name(),
"1",
31337,
]);

return ethers.Signature.from(
await signer.signTypedData(
{
name,
version,
chainId,
verifyingContract: token.target,
},
{
Permit: [
{
name: "owner",
type: "address",
},
{
name: "spender",
type: "address",
},
{
name: "value",
type: "uint256",
},
{
name: "nonce",
type: "uint256",
},
{
name: "deadline",
type: "uint256",
},
],
},
{
owner: signer.address,
spender,
value,
nonce,
deadline,
}
)
);
}

describe("ERC20Permit", function () {
it("ERC20 permit", async function () {
const accounts = await ethers.getSigners(1);
const signer = accounts[0];

const OurToken = await ethers.getContractFactory("OurToken");
const ourToken = await OurToken.deploy();
await ourToken.waitForDeployment();

// assign the token contract address to vault contract

const Vault = await ethers.getContractFactory("Vault");
const vault = await Vault.deploy(ourToken.target);
await vault.waitForDeployment();

// amount of tokens to be minted
const amount = 1000;
// call mint function
await ourToken.mint(signer.address, amount);

const deadline = ethers.MaxUint256;

const { v, r, s } = await getPermitSignature(
signer,
ourToken,
vault.target,
amount,
deadline
);

await vault.depositWithPermit(amount, deadline, v, r, s);

// test cases
expect(await ourToken.balanceOf(vault.target)).to.equal(amount);
});
});

0 comments on commit b93f1a5

Please sign in to comment.