Skip to content

Instantly share code, notes, and snippets.

@cupOJoseph
Created February 12, 2021 05:44
Show Gist options
  • Save cupOJoseph/0dfafb0f5c3386343860c2b39f802c57 to your computer and use it in GitHub Desktop.
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=
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);
}
}
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);
}
}
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 line is added to create a gist. Empty file is not allowed.
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);
}
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;
}
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;
}
}
contract LibraryLockDataLayout {
bool public initialized = false;
}
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
}
}
// 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();
}*/
}
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;
}
}
pragma solidity ^0.6.12;
import "./niftyChess.sol";
contract NiftyChessV2 is niftyChess {
function newMintFunction() public pure returns (uint256) {
return 1;
}
}
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;
}
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;
}
}
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;
}
}
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