Created
February 12, 2021 05:44
-
-
Save cupOJoseph/0dfafb0f5c3386343860c2b39f802c57 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.6.12+commit.27d51765.js&optimize=true&runs=200&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.6.0 <0.7.0; | |
import "./IAMB.sol"; | |
import "./ITokenManagement.sol"; | |
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v3.0.0/contracts/access/Ownable.sol"; | |
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v3.0.0/contracts/utils/Address.sol"; | |
contract AMBMediator is Ownable { | |
using Address for address; | |
constructor() public { | |
} | |
address public bridgeContractAddress; | |
address private otherSideContractAddress; | |
uint256 public requestGasLimit; | |
mapping (bytes32 => bool) public messageFixed; | |
function setBridgeContract(address _bridgeContract) external onlyOwner { | |
_setBridgeContract(_bridgeContract); | |
} | |
function _setBridgeContract(address _bridgeContract) internal { | |
require(_bridgeContract.isContract(), 'provided address is not a contract'); | |
bridgeContractAddress = _bridgeContract; | |
} | |
function bridgeContract() public view returns (IAMB) { | |
return IAMB(bridgeContractAddress); | |
} | |
function setMediatorContractOnOtherSide(address _mediatorContract) external onlyOwner { | |
_setMediatorContractOnOtherSide(_mediatorContract); | |
} | |
function _setMediatorContractOnOtherSide(address _mediatorContract) internal { | |
otherSideContractAddress = _mediatorContract; | |
} | |
function mediatorContractOnOtherSide() public view returns (address) { | |
return otherSideContractAddress; | |
} | |
function setRequestGasLimit(uint256 _requestGasLimit) external onlyOwner { | |
_setRequestGasLimit(_requestGasLimit); | |
} | |
function _setRequestGasLimit(uint256 _requestGasLimit) internal { | |
require(_requestGasLimit <= bridgeContract().maxGasPerTx(),'gas limit is higher than the Bridge maximum'); | |
requestGasLimit = _requestGasLimit; | |
} | |
/** | |
* @dev Tells the address that generated the message on the other network that is currently being executed by | |
* the AMB bridge. | |
* @return the address of the message sender. | |
*/ | |
function messageSender() internal view returns (address) { | |
return bridgeContract().messageSender(); | |
} | |
/** | |
* @dev Tells the id of the message originated on the other network. | |
* @return the id of the message originated on the other network. | |
*/ | |
function messageId() internal view returns (bytes32) { | |
return bridgeContract().messageId(); | |
} | |
function setMessageFixed(bytes32 _txHash) internal { | |
messageFixed[_txHash] = true; | |
} | |
function requestFailedMessageFix(bytes32 _txHash) external { | |
require(!bridgeContract().messageCallStatus(_txHash)); | |
require(bridgeContract().failedMessageReceiver(_txHash) == address(this)); | |
require(bridgeContract().failedMessageSender(_txHash) == mediatorContractOnOtherSide()); | |
bytes32 dataHash = bridgeContract().failedMessageDataHash(_txHash); | |
bytes4 methodSelector = ITokenManagement(address(0)).fixFailedMessage.selector; | |
bytes memory data = abi.encodeWithSelector(methodSelector, dataHash); | |
bridgeContract().requireToPassMessage(mediatorContractOnOtherSide(), data, requestGasLimit); | |
} | |
} |
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.6.12; | |
import "./Proxy.sol"; | |
import "./niftyChess.sol"; | |
contract Deployer { | |
event NewContract(address _contract); | |
address public logicA; | |
address public logicB; | |
address public lastDeployedProxy; | |
function step1_launchNiftyChess(address mediator) public { | |
logicA = address(new niftyChess()); | |
emit NewContract(logicA); | |
lastDeployedProxy = address(new Proxy(abi.encodeWithSignature("constructor1(address)", mediator), logicA)); | |
emit NewContract(lastDeployedProxy); | |
niftyChess(lastDeployedProxy).updateOwner(msg.sender); | |
} | |
} |
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.6.0 <0.7.0; | |
interface IAMB { | |
function messageSender() external view returns (address); | |
function maxGasPerTx() external view returns (uint256); | |
function transactionHash() external view returns (bytes32); | |
function messageId() external view returns (bytes32); | |
function messageSourceChainId() external view returns (bytes32); | |
function messageCallStatus(bytes32 _messageId) external view returns (bool); | |
function failedMessageDataHash(bytes32 _messageId) external view returns (bytes32); | |
function failedMessageReceiver(bytes32 _messageId) external view returns (address); | |
function failedMessageSender(bytes32 _messageId) external view returns (address); | |
function requireToPassMessage(address _contract, bytes calldata _data, uint256 _gas) external returns (bytes32); | |
} |
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
// this line is added to create a gist. Empty file is not allowed. |
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.6.0 <0.7.0; | |
interface INiftyToken { | |
function firstMint(address, string calldata, string calldata) external returns (uint256); | |
function mintBoard(address, string calldata) external returns (uint256); | |
function buyToken(uint256) external payable; | |
function lock(uint256) external; | |
function unlock(uint256, address) external; | |
function ownerOf(uint256) external view returns (address); | |
function getHashById(uint256) external returns (bytes32); | |
function tokenURI(uint256) external returns (string memory); | |
} |
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.6.0 <0.7.0; | |
interface ITokenManagement { | |
function mint(address to, uint256 tokenId, string calldata inkUrl, string calldata jsonUrl) external returns (uint256); | |
function fixFailedMessage(bytes32 _dataHash) external; | |
} |
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.6.12; | |
import "./LibraryLockDataLayout.sol"; | |
contract LibraryLock is LibraryLockDataLayout { | |
// Ensures no one can manipulate the Logic Contract once it is deployed. | |
// PARITY WALLET HACK PREVENTION | |
modifier delegatedOnly() { | |
require(initialized == true, "The library is locked. No direct 'call' is allowed"); | |
_; | |
} | |
function initialize() internal { | |
initialized = true; | |
} | |
} |
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
contract LibraryLockDataLayout { | |
bool public initialized = false; | |
} |
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.7.0; | |
contract MyToken{ | |
address owner; //who should get our tokens to begin with? | |
mapping (address => uint256) public balances; | |
constructor() public { | |
owner = msg.sender; //msg.sender is special | |
//here, msg.sender is the account that deployed the contract | |
balances[owner] = 1000; | |
//mint the owner 1000 myTokens and put it in the mapping | |
} | |
function transfer(uint amount, address recipient) public { | |
require(balances[msg.sender] >= amount); | |
require(balances[msg.sender] - amount <= balances[msg.sender]); | |
require(balances[recipient] + amount >= balances[recipient]); | |
//safety first | |
balances[msg.sender] -= amount; | |
balances[recipient] += amount; | |
//that’s it | |
} | |
} |
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
// contracts/GameItem.sol | |
// SPDX-License-Identifier: MIT | |
pragma solidity ^0.6.12; | |
//import "https://github.com/opengsn/gsn/blob/master/packages/contracts/src/BaseRelayRecipient.sol"; | |
import "./Proxiable.sol"; | |
import "./NiftyDataLayout.sol"; | |
import "./LibraryLock.sol"; | |
contract niftyChess is ERC721, Proxiable, NiftyDataLayout, LibraryLock { | |
function updateCode(address newCode) public { | |
require(msg.sender == owner); | |
updateCodeAddress(newCode); | |
} | |
constructor() public ERC721("NiftyChess", "CHESS") { | |
} | |
function getOwner() public view returns(address){ | |
return owner; | |
} | |
//============= Registry Setters ===============// | |
function setBridgeMediatorAddress(address newMediatorAddress) public{ | |
require(msg.sender == owner, "Only owner can update this."); | |
bridgeMediatorAddress = newMediatorAddress; | |
} | |
function setTokenMainAddress(address newMainAddress) public{ | |
require(msg.sender == owner, "Only owner can update this."); | |
tokenMainAddress = newMainAddress; | |
} | |
function setTrustedForwarderAddress(address newForwarder) public{ | |
require(msg.sender == owner, "Only owner can update this."); | |
trustedForwarderAddress = newForwarder; | |
} | |
//============== End Registry ===================// | |
function constructor1(address mediator) public{ | |
owner = msg.sender; | |
minter = msg.sender; | |
price = 0; | |
bridgeMediatorAddress = mediator; | |
initialize(); | |
/** | |
name = "NiftyChess"; | |
symbol = "PAWN"; | |
// register the supported interfaces to conform to ERC721 via ERC165 | |
_registerInterface(type(IERC721).interfaceId); | |
_registerInterface(type(IERC721Metadata).interfaceId); | |
_registerInterface(type(IERC721Enumerable).interfaceId);**/ | |
} | |
function lock(uint256 _tokenId) external { | |
// | |
require(bridgeMediatorAddress == msg.sender, 'only the bridgeMediator can lock'); | |
address from = ownerOf(_tokenId); | |
_transfer(from, msg.sender, _tokenId); | |
} | |
function unlock(uint256 _tokenId, address _recipient) external { | |
require(msg.sender == bridgeMediatorAddress, 'only the bridgeMediator can unlock'); | |
require(msg.sender == ownerOf(_tokenId), 'the bridgeMediator does not hold this token'); | |
safeTransferFrom(_msgSender(), _recipient, _tokenId); | |
} | |
function updateMinter(address newMinter) public { | |
require(msg.sender == owner, "Only the owner can do that."); | |
minter = newMinter; | |
} | |
function updateOwner(address newOwner) public { | |
require(msg.sender == owner, "Only the owner can do that."); | |
owner = newOwner; | |
} | |
function updatePrice(uint256 newPrice) public{ | |
require(msg.sender == owner, "Only the owner can do that."); | |
price = newPrice; | |
} | |
function mintBoard(address player, string memory tokenURI, bytes32 movesHash) | |
public payable | |
returns (uint256) | |
{ | |
require(msg.value >= price, "You must include the award Price in your transaction."); | |
//every set of moves must be a unique hash | |
require(movesTaken[movesHash] == 0, "This game has already been minted because its hash exists in Nifty Chess."); | |
_tokenIds.increment(); | |
uint256 newItemId = _tokenIds.current(); | |
games[newItemId] = movesHash; | |
movesTaken[movesHash] = newItemId; | |
_mint(player, newItemId); | |
_setTokenURI(newItemId, tokenURI); | |
return newItemId; | |
} | |
function minterMint(address player, string memory tokenURI, bytes32 movesHash) | |
public payable | |
returns (uint256) | |
{ | |
require(msg.sender == minter, "You must be the minter to do this."); | |
//every set of moves must be a unique hash | |
require(movesTaken[movesHash] == 0, "This game has already been minted because its hash exists in Nifty Chess."); | |
_tokenIds.increment(); | |
uint256 newItemId = _tokenIds.current(); | |
games[newItemId] = movesHash; | |
movesTaken[movesHash] = newItemId; | |
_mint(player, newItemId); | |
_setTokenURI(newItemId, tokenURI); | |
return newItemId; | |
} | |
function tokenHashLookup(bytes32 hash) public returns(uint256){ | |
return movesTaken[hash]; | |
} | |
function getHashById(uint256 id) external returns(bytes32){ | |
return games[id]; | |
} | |
/*function _msgSender() internal override(BaseRelayRecipient, Context) view returns (address payable) { | |
return BaseRelayRecipient._msgSender(); | |
}*/ | |
} |
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.6.0 <0.7.0; | |
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v3.0.0/contracts/token/ERC721/ERC721.sol"; | |
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v3.0.0/contracts/utils/Counters.sol"; | |
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v3.0.0/contracts/access/Ownable.sol"; | |
import "./AMBMediator.sol"; | |
import "./ITokenManagement.sol"; | |
import "./IAMB.sol"; | |
contract NiftyMain is ERC721, Ownable, AMBMediator { | |
address mainRelayer; | |
address owner; | |
constructor() ERC721("Nifty Chess", "CHESS") public { | |
_setBaseURI('ipfs://ipfs/'); | |
mainRelayer = 0; | |
owner = msg.sender; | |
} | |
event mintedGame(uint256 id, string gameURL, bytes32 gameHash, address to, bytes32 msgId); | |
mapping (bytes32 => EnumerableSet.UintSet) private _gameTokens; | |
mapping (uint256 => string) public tokenGame; | |
function mint(address to, uint256 tokenId, bytes32 _gameHash, string gameURL) external returns (uint256) { | |
require(msg.sender == address(bridgeContract())); | |
require(bridgeContract().messageSender() == mediatorContractOnOtherSide()); | |
_gameTokens[gameURL].add(tokenId); //make games lookup able by url | |
tokenGame[tokenId] = inkUrl; | |
_safeMint(to, tokenId); | |
_setTokenURI(tokenId, jsonUrl); | |
bytes32 msgId = messageId(); | |
emit mintedGame(tokenId, inkUrl, _gameHash, to, msgId); | |
return tokenId; | |
} | |
function inkTokenCount(string memory _inkUrl) public view returns(uint256) { | |
uint256 _inkTokenCount = _gameTokens[_inkUrl].length(); | |
return _inkTokenCount; | |
} | |
function inkTokenByIndex(string memory inkUrl, uint256 index) public view returns (uint256) { | |
return _gameTokens[inkUrl].at(index); | |
} | |
//======== for future use with unimplimented main net relayer to send back to xdai. ========// | |
function downgradeToXdai(address to, uint256 tokenId){ | |
require(mainRelayer != 0, "No mainRelayer Set."); | |
require(msg.sender == ownerOf(tokenId)); //you are allowed to move this token | |
require(mainRelayer == to); //you have to send to the to address. | |
} | |
//update mainRelayer address. owner only | |
function setMainRelayer(address newRelayer){ | |
require(msg.sender == owner); | |
mainRelayer = newRelayer; | |
} | |
} |
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.6.12; | |
import "./niftyChess.sol"; | |
contract NiftyChessV2 is niftyChess { | |
function newMintFunction() public pure returns (uint256) { | |
return 1; | |
} | |
} |
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.6.12; | |
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v3.0.0/contracts/utils/Counters.sol"; | |
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v3.0.0/contracts/token/ERC721/ERC721.sol"; | |
import "./LibraryLockDataLayout.sol"; | |
contract NiftyDataLayout is LibraryLockDataLayout{ | |
using Counters for Counters.Counter; | |
Counters.Counter public _tokenIds; | |
mapping(bytes32 => uint256) public movesTaken; | |
mapping(uint256 => bytes32) public games; | |
address owner; | |
address minter; | |
uint256 price; | |
address public niftyRegistry; | |
uint256 public relayPrice; | |
address payable public feeReceiver; | |
address public bridgeMediatorAddress; | |
address public tokenMainAddress; | |
address public trustedForwarderAddress; | |
} |
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.6.0 <0.7.0; | |
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v3.0.0/contracts/access/Ownable.sol"; | |
import "./AMBMediator.sol"; | |
import "./INiftyToken.sol"; | |
contract NiftyMediator is Ownable, AMBMediator { | |
constructor() public { | |
} | |
event tokenSentViaBridge(uint256 _tokenId, bytes32 _msgId); | |
event failedMessageFixed(bytes32 _msgId, address _recipient, uint256 _tokenId); | |
event newPrice(uint256 price); | |
uint256 public relayPrice; | |
address public niftyChessAddress; | |
address payable public feeReceiverAddress; | |
function setFeeR(address payable feeReceiver) public onlyOwner{ | |
feeReceiverAddress = feeReceiver; | |
} | |
function setNiftyChessAddress(address tokenAddress) public onlyOwner{ | |
niftyChessAddress = tokenAddress; | |
} | |
function setRelayPrice(uint256 _price) public onlyOwner { | |
relayPrice = _price; | |
emit newPrice(_price); | |
} | |
function niftyToken() private view returns (INiftyToken) { | |
return INiftyToken(niftyChessAddress); | |
} | |
mapping (bytes32 => uint256) private msgTokenId; | |
mapping (bytes32 => address) private msgRecipient; | |
function _relayToken(uint256 _tokenId) internal returns (bytes32) { | |
niftyToken().lock(_tokenId); | |
bytes32 gameHash = niftyToken().getHashById(_tokenId); | |
string memory tokenURI = niftyToken().tokenURI(_tokenId); | |
bytes4 methodSelector = ITokenManagement(address(0)).mint.selector; | |
bytes memory data = abi.encodeWithSelector(methodSelector,msg.sender, _tokenId, tokenURI, gameHash); | |
bytes32 msgId = bridgeContract().requireToPassMessage( | |
mediatorContractOnOtherSide(), | |
data, | |
requestGasLimit | |
); | |
msgTokenId[msgId] = _tokenId; | |
msgRecipient[msgId] = _msgSender(); | |
emit tokenSentViaBridge(_tokenId, msgId); | |
return msgId; | |
} | |
function relayToken(uint256 _tokenId) external payable returns (bytes32) { | |
require(msg.sender == niftyToken().ownerOf(_tokenId), 'only the owner can upgrade!'); | |
require(msg.value >= relayPrice, "Amount sent too small"); | |
feeReceiverAddress.transfer(msg.value); | |
return _relayToken(_tokenId); | |
} | |
function fixFailedMessage(bytes32 _msgId) external { | |
require(msg.sender == address(bridgeContract())); | |
require(bridgeContract().messageSender() == mediatorContractOnOtherSide()); | |
require(!messageFixed[_msgId]); | |
address _recipient = msgRecipient[_msgId]; | |
uint256 _tokenId = msgTokenId[_msgId]; | |
messageFixed[_msgId] = true; | |
niftyToken().unlock(_tokenId, _recipient); | |
emit failedMessageFixed(_msgId, _recipient, _tokenId); | |
} | |
address public trustedForwarder; | |
function setTrustedForwarder(address _trustedForwarder) public onlyOwner { | |
trustedForwarder = _trustedForwarder; | |
} | |
function getTrustedForwarder() public view returns(address) { | |
return trustedForwarder; | |
} | |
} | |
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.6.12; | |
contract Proxiable { | |
// Code position in storage is bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1) = "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" | |
function updateCodeAddress(address newAddress) internal { | |
require( | |
bytes32(0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc) == Proxiable(newAddress).proxiableUUID(), | |
"Not compatible" | |
); | |
assembly { // solium-disable-line | |
sstore(0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc, newAddress) | |
} | |
} | |
function proxiableUUID() public pure returns (bytes32) { | |
return 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; | |
} | |
} |
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.6.12; | |
contract Proxy { | |
// Code position in storage is keccak256("PROXIABLE") = "0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7" | |
constructor(bytes memory constructData, address contractLogic) public { | |
// save the code address | |
assembly { // solium-disable-line | |
sstore(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7, contractLogic) | |
} | |
(bool success, bytes memory _ ) = contractLogic.delegatecall(constructData); // solium-disable-line | |
require(success, "Construction failed"); | |
} | |
fallback() external payable { | |
assembly { // solium-disable-line | |
let contractLogic := sload(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7) | |
calldatacopy (0x0, 0x0, calldatasize()) | |
let success := delegatecall(sub(gas(), 10000), contractLogic, 0x0, calldatasize(), 0, 0) | |
let retSz := returndatasize() | |
returndatacopy(0, 0, retSz) | |
switch success | |
case 0 { | |
revert(0, retSz) | |
} | |
default { | |
return(0, retSz) | |
} | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment