Last active
March 19, 2019 17:06
-
-
Save jdkanani/ffd27a8d11bd5178ab3451ca6a99c971 to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.5.4+commit.9549d8ff.js&optimize=true&gist=
This file contains hidden or 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
// pragma solidity >=0.4.22 <0.6.0; | |
pragma solidity >=0.5.2 <0.6.0; | |
import { ERC20 } from "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol"; | |
import { ERC20Detailed } from "openzeppelin-solidity/contracts/token/ERC20/ERC20Detailed.sol"; | |
import { LibTokenTransferOrder } from "./libs/TokenTransferOrder.sol"; | |
import { ECRecover } from "./libs/ECRecover.sol"; | |
contract ChildERC20 is ERC20, ERC20Detailed, LibTokenTransferOrder, ECRecover { | |
mapping(bytes32 => bool) public disabledHashes; | |
constructor() public ERC20Detailed("ChildERC20", "CHE", 18) {} | |
function mint(uint256 amount) public { | |
_mint(msg.sender, amount); | |
} | |
function transferWithSig(bytes memory sig, uint256 amount, bytes32 data, uint256 expiration, address to) public returns (address) { | |
require(amount > 0); | |
require(expiration == 0 || block.number <= expiration, "Signature is expired"); | |
bytes32 dataHash = getTokenTransferOrderHash( | |
msg.sender, | |
amount, | |
data, | |
expiration | |
); | |
require(disabledHashes[dataHash] == false, "Sig deactivated"); | |
disabledHashes[dataHash] = true; | |
// recover address and send tokens | |
address from = recover(dataHash, sig); | |
_transfer(from, to, amount); | |
return from; | |
} | |
} |
This file contains hidden or 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
pragma solidity >=0.5.2 <0.6.0; | |
import { ERC721Full } from "openzeppelin-solidity/contracts/token/ERC721/ERC721Full.sol"; | |
import { LibTokenTransferOrder } from "./libs/TokenTransferOrder.sol"; | |
import { ECRecover } from "./libs/ECRecover.sol"; | |
contract ChildERC721 is ERC721Full, LibTokenTransferOrder, ECRecover { | |
mapping(bytes32 => bool) public disabledHashes; | |
// constructor | |
constructor () ERC721Full("Test NFT", "NFT") public { | |
} | |
function mint(uint256 tokenId) public { | |
_mint(msg.sender, tokenId); | |
} | |
function transferWithSig(bytes memory sig, uint256 tokenId, bytes32 data, uint256 expiration, address to) public returns (address) { | |
require(expiration == 0 || block.number <= expiration, "Signature is expired"); | |
bytes32 dataHash = getTokenTransferOrderHash( | |
msg.sender, | |
tokenId, | |
data, | |
expiration | |
); | |
require(disabledHashes[dataHash] == false, "Sig deactivated"); | |
disabledHashes[dataHash] = true; | |
// recover address and send tokens | |
address from = recover(dataHash, sig); | |
// safeTransferFrom | |
_transferFrom(from, to, tokenId); | |
require(_checkOnERC721Received(from, to, tokenId, "")); | |
return from; | |
} | |
} |
This file contains hidden or 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
// pragma solidity >=0.4.22 <0.6.0; | |
pragma solidity >=0.5.2 <0.6.0; | |
contract ECRecover { | |
function recover(bytes32 dataHash, bytes memory sig) internal pure returns (address) { | |
bytes32 hash = dataHash; // keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", dataHash)); | |
bytes32 r; | |
bytes32 s; | |
uint8 v; | |
// Check the signature length | |
if (sig.length != 65) { | |
return address(0x0); | |
} | |
assembly { | |
r := mload(add(sig, 32)) | |
s := mload(add(sig, 64)) | |
v := byte(0, mload(add(sig, 96))) | |
} | |
return ecrecover(hash, v, r, s); | |
} | |
} |
This file contains hidden or 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
// pragma solidity >=0.4.22 <0.6.0; | |
pragma solidity >=0.5.2 <0.6.0; | |
contract LibEIP712Domain { | |
string constant internal EIP712_DOMAIN_SCHEMA = "EIP712Domain(string name,string version,uint256 chainId,address contract)"; | |
bytes32 constant public EIP712_DOMAIN_SCHEMA_HASH = keccak256(abi.encodePacked(EIP712_DOMAIN_SCHEMA)); | |
string constant internal EIP712_DOMAIN_NAME = "Matic Network"; | |
string constant internal EIP712_DOMAIN_VERSION = "1"; | |
uint256 constant internal EIP712_DOMAIN_CHAINID = 13; | |
bytes32 public EIP712_DOMAIN_HASH; | |
constructor () public { | |
EIP712_DOMAIN_HASH = keccak256(abi.encode( | |
EIP712_DOMAIN_SCHEMA_HASH, | |
keccak256(bytes(EIP712_DOMAIN_NAME)), | |
keccak256(bytes(EIP712_DOMAIN_VERSION)), | |
EIP712_DOMAIN_CHAINID, | |
address(this) | |
)); | |
} | |
function hashEIP712Message(bytes32 hashStruct) internal view returns (bytes32 result) { | |
bytes32 domainHash = EIP712_DOMAIN_HASH; | |
// Assembly for more efficient computing: | |
// keccak256(abi.encode( | |
// EIP191_HEADER, | |
// domainHash, | |
// hashStruct | |
// )); | |
assembly { | |
// Load free memory pointer | |
let memPtr := mload(64) | |
mstore(memPtr, 0x1901000000000000000000000000000000000000000000000000000000000000) // EIP191 header | |
mstore(add(memPtr, 2), domainHash) // EIP712 domain hash | |
mstore(add(memPtr, 34), hashStruct) // Hash of struct | |
// Compute hash | |
result := keccak256(memPtr, 66) | |
} | |
return result; | |
} | |
} |
This file contains hidden or 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
pragma solidity >=0.5.2 <0.6.0; | |
interface MarketplaceToken { | |
function transferWithSig(bytes calldata sig, uint256 tokenIdOrAmount, bytes32 data, uint256 expiration, address to) external returns (address); | |
} | |
contract Marketplace { | |
function executeOrder( | |
address token1, | |
bytes memory sig1, | |
uint256 tokenIdOrAmount1, | |
address token2, | |
bytes memory sig2, | |
uint256 tokenIdOrAmount2, | |
bytes32 orderId, | |
uint256 expiration, | |
address address2 // address of second participant | |
) public { | |
// Transferring token1 tokens from `address1` to `msg.sender` | |
address _address1 = MarketplaceToken(token1).transferWithSig( | |
sig1, | |
tokenIdOrAmount1, | |
keccak256(abi.encodePacked(orderId, token2, tokenIdOrAmount2)), | |
expiration, | |
address2 | |
); | |
// Transferring token2 from `msg.sender` to `msg.sender` | |
address _address2 = MarketplaceToken(token2).transferWithSig( | |
sig2, | |
tokenIdOrAmount2, | |
keccak256(abi.encodePacked(orderId, token1, tokenIdOrAmount1)), | |
expiration, | |
_address1 | |
); | |
require(address2 == _address2); | |
} | |
} |
This file contains hidden or 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
// pragma solidity >=0.4.22 <0.6.0; | |
pragma solidity >=0.5.2 <0.6.0; | |
import { LibEIP712Domain } from "./EIP712.sol"; | |
contract LibTokenTransferOrder is LibEIP712Domain { | |
string constant internal EIP712_TOKEN_TRANSFER_ORDER_SCHEMA = "TokenTransferOrder(address spender,uint256 tokenIdOrAmount,bytes32 data,uint256 expiration)"; | |
bytes32 constant public EIP712_TOKEN_TRANSFER_ORDER_SCHEMA_HASH = keccak256(abi.encodePacked(EIP712_TOKEN_TRANSFER_ORDER_SCHEMA)); | |
struct TokenTransferOrder { | |
address spender; | |
uint256 tokenIdOrAmount; | |
bytes32 data; | |
uint256 expiration; | |
} | |
function getTokenTransferOrderHash(address spender, uint256 tokenIdOrAmount, bytes32 data, uint256 expiration) | |
public | |
view | |
returns (bytes32 orderHash) | |
{ | |
orderHash = hashEIP712Message(hashTokenTransferOrder(spender, tokenIdOrAmount, data, expiration)); | |
} | |
function hashTokenTransferOrder(address spender, uint256 tokenIdOrAmount, bytes32 data, uint256 expiration) | |
internal | |
pure | |
returns (bytes32 result) | |
{ | |
bytes32 schemaHash = EIP712_TOKEN_TRANSFER_ORDER_SCHEMA_HASH; | |
// Assembly for more efficiently computing: | |
// return keccak256(abi.encode( | |
// schemaHash, | |
// spender, | |
// tokenIdOrAmount, | |
// data, | |
// expiration | |
// )); | |
assembly { | |
// Load free memory pointer | |
let memPtr := mload(64) | |
mstore(memPtr, schemaHash) // hash of schema | |
mstore(add(memPtr, 32), and(spender, 0xffffffffffffffffffffffffffffffffffffffff)) // spender | |
mstore(add(memPtr, 64), tokenIdOrAmount) // tokenIdOrAmount | |
mstore(add(memPtr, 96), data) // hash of data | |
mstore(add(memPtr, 128), expiration) // expiration | |
// Compute hash | |
result := keccak256(memPtr, 160) | |
} | |
return result; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Starting migrations...
1_initial_migration.js
2_marketplace.js
Replacing 'ChildERC20'
Replacing 'ChildERC721'
Replacing 'Marketplace'
Summary