ERC1363 support
This commit is contained in:
parent
e77f44b3c1
commit
77a0cf4461
|
@ -8,12 +8,16 @@ import "@openzeppelin/contracts/access/Ownable.sol";
|
||||||
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";
|
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";
|
||||||
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol";
|
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol";
|
||||||
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20FlashMint.sol";
|
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20FlashMint.sol";
|
||||||
|
import {Address} from "@openzeppelin/contracts/utils/Address.sol";
|
||||||
|
import "erc-payable-token/contracts/token/ERC1363/IERC1363.sol";
|
||||||
|
import "erc-payable-token/contracts/token/ERC1363/IERC1363Spender.sol";
|
||||||
|
import "erc-payable-token/contracts/token/ERC1363/IERC1363Receiver.sol";
|
||||||
|
|
||||||
|
abstract contract AbstractGrans is IERC1363, ERC20, ERC20Burnable, Pausable, Ownable, ERC20Permit, ERC20Votes, ERC20FlashMint {
|
||||||
|
using Address for address;
|
||||||
|
|
||||||
|
constructor() ERC20("10Grans", "GRANS") ERC20Permit("10Grans") {}
|
||||||
|
|
||||||
abstract contract AbstractGrans is ERC20, ERC20Burnable, Pausable, Ownable, ERC20Permit, ERC20Votes, ERC20FlashMint {
|
|
||||||
constructor() ERC20("10Grans", "GRANS") ERC20Permit("10Grans") {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function pause() public onlyOwner {
|
function pause() public onlyOwner {
|
||||||
_pause();
|
_pause();
|
||||||
}
|
}
|
||||||
|
@ -22,6 +26,14 @@ abstract contract AbstractGrans is ERC20, ERC20Burnable, Pausable, Ownable, ERC2
|
||||||
_unpause();
|
_unpause();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev See {IERC165-supportsInterface}.
|
||||||
|
*/
|
||||||
|
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165) returns (bool) {
|
||||||
|
return interfaceId == type(IERC1363).interfaceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function _beforeTokenTransfer(address from, address to, uint256 amount) internal override whenNotPaused {
|
function _beforeTokenTransfer(address from, address to, uint256 amount) internal override whenNotPaused {
|
||||||
super._beforeTokenTransfer(from, to, amount);
|
super._beforeTokenTransfer(from, to, amount);
|
||||||
}
|
}
|
||||||
|
@ -40,11 +52,151 @@ abstract contract AbstractGrans is ERC20, ERC20Burnable, Pausable, Ownable, ERC2
|
||||||
super._burn(account, amount);
|
super._burn(account, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
function balanceOf(address account) public view virtual override(ERC20) returns (uint256) {
|
function balanceOf(address account) public view virtual override(ERC20, IERC20) returns (uint256) {
|
||||||
return ERC20.balanceOf(account);
|
return ERC20.balanceOf(account);
|
||||||
}
|
}
|
||||||
|
|
||||||
function transferFrom(address sender, address recipient, uint256 amount) public virtual override(ERC20) returns (bool) {
|
function transferFrom(address sender, address recipient, uint256 amount) public virtual override(ERC20, IERC20) returns (bool) {
|
||||||
return ERC20.transferFrom(sender, recipient, amount);
|
return ERC20.transferFrom(sender, recipient, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Transfer tokens to a specified address and then execute a callback on `to`.
|
||||||
|
* @param to The address to transfer to.
|
||||||
|
* @param amount The amount to be transferred.
|
||||||
|
* @return A boolean that indicates if the operation was successful.
|
||||||
|
*/
|
||||||
|
function transferAndCall(address to, uint256 amount) public virtual override returns (bool) {
|
||||||
|
return transferAndCall(to, amount, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Transfer tokens to a specified address and then execute a callback on `to`.
|
||||||
|
* @param to The address to transfer to
|
||||||
|
* @param amount The amount to be transferred
|
||||||
|
* @param data Additional data with no specified format
|
||||||
|
* @return A boolean that indicates if the operation was successful.
|
||||||
|
*/
|
||||||
|
function transferAndCall(address to, uint256 amount, bytes memory data) public virtual override returns (bool) {
|
||||||
|
transfer(to, amount);
|
||||||
|
require(_checkOnTransferReceived(_msgSender(), to, amount, data), "ERC1363: receiver returned wrong data");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Transfer tokens from one address to another and then execute a callback on `to`.
|
||||||
|
* @param from The address which you want to send tokens from
|
||||||
|
* @param to The address which you want to transfer to
|
||||||
|
* @param amount The amount of tokens to be transferred
|
||||||
|
* @return A boolean that indicates if the operation was successful.
|
||||||
|
*/
|
||||||
|
function transferFromAndCall(address from, address to, uint256 amount) public virtual override returns (bool) {
|
||||||
|
return transferFromAndCall(from, to, amount, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Transfer tokens from one address to another and then execute a callback on `to`.
|
||||||
|
* @param from The address which you want to send tokens from
|
||||||
|
* @param to The address which you want to transfer to
|
||||||
|
* @param amount The amount of tokens to be transferred
|
||||||
|
* @param data Additional data with no specified format
|
||||||
|
* @return A boolean that indicates if the operation was successful.
|
||||||
|
*/
|
||||||
|
function transferFromAndCall(
|
||||||
|
address from,
|
||||||
|
address to,
|
||||||
|
uint256 amount,
|
||||||
|
bytes memory data
|
||||||
|
) public virtual override returns (bool) {
|
||||||
|
transferFrom(from, to, amount);
|
||||||
|
require(_checkOnTransferReceived(from, to, amount, data), "ERC1363: receiver returned wrong data");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Approve spender to transfer tokens and then execute a callback on `spender`.
|
||||||
|
* @param spender The address allowed to transfer to
|
||||||
|
* @param amount The amount allowed to be transferred
|
||||||
|
* @return A boolean that indicates if the operation was successful.
|
||||||
|
*/
|
||||||
|
function approveAndCall(address spender, uint256 amount) public virtual override returns (bool) {
|
||||||
|
return approveAndCall(spender, amount, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Approve spender to transfer tokens and then execute a callback on `spender`.
|
||||||
|
* @param spender The address allowed to transfer to.
|
||||||
|
* @param amount The amount allowed to be transferred.
|
||||||
|
* @param data Additional data with no specified format.
|
||||||
|
* @return A boolean that indicates if the operation was successful.
|
||||||
|
*/
|
||||||
|
function approveAndCall(address spender, uint256 amount, bytes memory data) public virtual override returns (bool) {
|
||||||
|
approve(spender, amount);
|
||||||
|
require(_checkOnApprovalReceived(spender, amount, data), "ERC1363: spender returned wrong data");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Internal function to invoke {IERC1363Receiver-onTransferReceived} on a target address.
|
||||||
|
* The call is not executed if the target address is not a contract.
|
||||||
|
* @param sender address Representing the previous owner of the given token amount
|
||||||
|
* @param recipient address Target address that will receive the tokens
|
||||||
|
* @param amount uint256 The amount mount of tokens to be transferred
|
||||||
|
* @param data bytes Optional data to send along with the call
|
||||||
|
* @return whether the call correctly returned the expected magic value
|
||||||
|
*/
|
||||||
|
function _checkOnTransferReceived(
|
||||||
|
address sender,
|
||||||
|
address recipient,
|
||||||
|
uint256 amount,
|
||||||
|
bytes memory data
|
||||||
|
) internal virtual returns (bool) {
|
||||||
|
if (!recipient.isContract()) {
|
||||||
|
revert("ERC1363: transfer to non contract address");
|
||||||
|
}
|
||||||
|
|
||||||
|
try IERC1363Receiver(recipient).onTransferReceived(_msgSender(), sender, amount, data) returns (bytes4 retval) {
|
||||||
|
return retval == IERC1363Receiver.onTransferReceived.selector;
|
||||||
|
} catch (bytes memory reason) {
|
||||||
|
if (reason.length == 0) {
|
||||||
|
revert("ERC1363: transfer to non ERC1363Receiver implementer");
|
||||||
|
} else {
|
||||||
|
/// @solidity memory-safe-assembly
|
||||||
|
assembly {
|
||||||
|
revert(add(32, reason), mload(reason))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Internal function to invoke {IERC1363Receiver-onApprovalReceived} on a target address.
|
||||||
|
* The call is not executed if the target address is not a contract.
|
||||||
|
* @param spender address The address which will spend the funds
|
||||||
|
* @param amount uint256 The amount of tokens to be spent
|
||||||
|
* @param data bytes Optional data to send along with the call
|
||||||
|
* @return whether the call correctly returned the expected magic value
|
||||||
|
*/
|
||||||
|
function _checkOnApprovalReceived(
|
||||||
|
address spender,
|
||||||
|
uint256 amount,
|
||||||
|
bytes memory data
|
||||||
|
) internal virtual returns (bool) {
|
||||||
|
if (!spender.isContract()) {
|
||||||
|
revert("ERC1363: approve a non contract address");
|
||||||
|
}
|
||||||
|
|
||||||
|
try IERC1363Spender(spender).onApprovalReceived(_msgSender(), amount, data) returns (bytes4 retval) {
|
||||||
|
return retval == IERC1363Spender.onApprovalReceived.selector;
|
||||||
|
} catch (bytes memory reason) {
|
||||||
|
if (reason.length == 0) {
|
||||||
|
revert("ERC1363: approve a non ERC1363Spender implementer");
|
||||||
|
} else {
|
||||||
|
/// @solidity memory-safe-assembly
|
||||||
|
assembly {
|
||||||
|
revert(add(32, reason), mload(reason))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,17 @@
|
||||||
import { HardhatUserConfig } from "hardhat/config";
|
import { HardhatUserConfig } from "hardhat/config";
|
||||||
import "@nomicfoundation/hardhat-toolbox";
|
import "@nomicfoundation/hardhat-toolbox";
|
||||||
|
import "hardhat-contract-sizer";
|
||||||
|
|
||||||
const config: HardhatUserConfig = {
|
const config: HardhatUserConfig = {
|
||||||
solidity: "0.8.19",
|
solidity: {
|
||||||
|
version: "0.8.19",
|
||||||
|
settings: {
|
||||||
|
optimizer: {
|
||||||
|
enabled: true,
|
||||||
|
runs: 200
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default config;
|
export default config;
|
||||||
|
|
|
@ -7,14 +7,16 @@
|
||||||
"": {
|
"": {
|
||||||
"name": "10grans-ng",
|
"name": "10grans-ng",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "ISC",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@arbitrum/token-bridge-contracts": "^1.0.0-beta.0",
|
"@arbitrum/token-bridge-contracts": "^1.0.0-beta.0",
|
||||||
"@openzeppelin/contracts": "^4.9.3"
|
"@openzeppelin/contracts": "^4.9.3",
|
||||||
|
"erc-payable-token": "^4.9.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nomicfoundation/hardhat-toolbox": "^3.0.0",
|
"@nomicfoundation/hardhat-toolbox": "^3.0.0",
|
||||||
"hardhat": "^2.17.1",
|
"hardhat": "^2.17.1",
|
||||||
|
"hardhat-contract-sizer": "^2.10.0",
|
||||||
"prettier": "^3.0.1",
|
"prettier": "^3.0.1",
|
||||||
"prettier-plugin-solidity": "^1.1.3"
|
"prettier-plugin-solidity": "^1.1.3"
|
||||||
}
|
}
|
||||||
|
@ -100,6 +102,16 @@
|
||||||
"case": "^1.6.3"
|
"case": "^1.6.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@colors/colors": {
|
||||||
|
"version": "1.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz",
|
||||||
|
"integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.1.90"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@cspotcode/source-map-support": {
|
"node_modules/@cspotcode/source-map-support": {
|
||||||
"version": "0.8.1",
|
"version": "0.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
|
||||||
|
@ -4150,6 +4162,14 @@
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/erc-payable-token": {
|
||||||
|
"version": "4.9.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/erc-payable-token/-/erc-payable-token-4.9.3.tgz",
|
||||||
|
"integrity": "sha512-hAkSyH+TfXvbTyrlcOpGhzQkSTgrRWkAktOhRUL2vY2sztYr3twjxhPydaK6CI4uf9+nk6SpujiRrPqxoDOd/w==",
|
||||||
|
"dependencies": {
|
||||||
|
"@openzeppelin/contracts": "4.9.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/es-abstract": {
|
"node_modules/es-abstract": {
|
||||||
"version": "1.22.1",
|
"version": "1.22.1",
|
||||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz",
|
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz",
|
||||||
|
@ -5814,6 +5834,105 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/hardhat-contract-sizer": {
|
||||||
|
"version": "2.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/hardhat-contract-sizer/-/hardhat-contract-sizer-2.10.0.tgz",
|
||||||
|
"integrity": "sha512-QiinUgBD5MqJZJh1hl1jc9dNnpJg7eE/w4/4GEnrcmZJJTDbVFNe3+/3Ep24XqISSkYxRz36czcPHKHd/a0dwA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"chalk": "^4.0.0",
|
||||||
|
"cli-table3": "^0.6.0",
|
||||||
|
"strip-ansi": "^6.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"hardhat": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/hardhat-contract-sizer/node_modules/ansi-styles": {
|
||||||
|
"version": "4.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||||
|
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"color-convert": "^2.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/hardhat-contract-sizer/node_modules/chalk": {
|
||||||
|
"version": "4.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||||
|
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-styles": "^4.1.0",
|
||||||
|
"supports-color": "^7.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/hardhat-contract-sizer/node_modules/cli-table3": {
|
||||||
|
"version": "0.6.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz",
|
||||||
|
"integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"string-width": "^4.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "10.* || >= 12.*"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@colors/colors": "1.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/hardhat-contract-sizer/node_modules/color-convert": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"color-name": "~1.1.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/hardhat-contract-sizer/node_modules/color-name": {
|
||||||
|
"version": "1.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||||
|
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/hardhat-contract-sizer/node_modules/has-flag": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/hardhat-contract-sizer/node_modules/supports-color": {
|
||||||
|
"version": "7.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||||
|
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"has-flag": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/hardhat-gas-reporter": {
|
"node_modules/hardhat-gas-reporter": {
|
||||||
"version": "1.0.9",
|
"version": "1.0.9",
|
||||||
"resolved": "https://registry.npmjs.org/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.9.tgz",
|
"resolved": "https://registry.npmjs.org/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.9.tgz",
|
||||||
|
|
|
@ -21,11 +21,13 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nomicfoundation/hardhat-toolbox": "^3.0.0",
|
"@nomicfoundation/hardhat-toolbox": "^3.0.0",
|
||||||
"hardhat": "^2.17.1",
|
"hardhat": "^2.17.1",
|
||||||
|
"hardhat-contract-sizer": "^2.10.0",
|
||||||
"prettier": "^3.0.1",
|
"prettier": "^3.0.1",
|
||||||
"prettier-plugin-solidity": "^1.1.3"
|
"prettier-plugin-solidity": "^1.1.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@arbitrum/token-bridge-contracts": "^1.0.0-beta.0",
|
"@arbitrum/token-bridge-contracts": "^1.0.0-beta.0",
|
||||||
"@openzeppelin/contracts": "^4.9.3"
|
"@openzeppelin/contracts": "^4.9.3",
|
||||||
|
"erc-payable-token": "^4.9.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue