github.com/amazechain/amc@v0.1.3/contracts/deposit/FUJI/staking.sol (about) 1 // SPDX-License-Identifier: MIT 2 pragma solidity ^0.8.17; 3 4 import "@openzeppelin/contracts@v4.9.0/access/Ownable.sol"; 5 import "@openzeppelin/contracts@v4.9.0/token/ERC721/ERC721.sol"; 6 import "@openzeppelin/contracts@v4.9.0/token/ERC721/IERC721Receiver.sol"; 7 import "@openzeppelin/contracts@v4.9.0/token/ERC721/IERC721.sol"; 8 import "@openzeppelin/contracts-upgradeable@v4.9.0/proxy/utils/Initializable.sol"; 9 import "./IDeposit.sol"; 10 11 contract StakingFUJI is IDeposit, IERC721Receiver, Ownable { 12 IERC721 token; 13 mapping(uint256 => bool) T200NFT; 14 mapping(uint256 => bool) T800NFT; 15 mapping(uint256 => bool) T2000NFT; 16 17 mapping(address => uint256) depoistNFT; 18 mapping(address => uint256) depositExpire; 19 20 mapping(uint256 => address) withdrawIDToAddress; 21 mapping(address => uint256) withdrawAddressToID; 22 // mapping(address => uint256) withdrawNFT; 23 24 constructor(address fujiAddr, address fujiAdminAddress) Ownable() { 25 token = IERC721(fujiAddr); 26 token.setApprovalForAll(fujiAdminAddress, true); 27 } 28 29 function addT200TokendIDs(uint256[] calldata T200TokenIDs) public virtual onlyOwner { 30 for (uint i = 0; i < T200TokenIDs.length; i++) { 31 T200NFT[T200TokenIDs[i]] = true; 32 } 33 } 34 35 function addT800TokendIDs(uint256[] calldata T800TokenIDs) public virtual onlyOwner { 36 for (uint i = 0; i < T800TokenIDs.length; i++) { 37 T800NFT[T800TokenIDs[i]] = true; 38 } 39 } 40 41 function addT2000TokendIDs(uint256[] calldata T2000TokenIDs) public virtual onlyOwner { 42 for (uint i = 0; i < T2000TokenIDs.length; i++) { 43 T2000NFT[T2000TokenIDs[i]] = true; 44 } 45 } 46 47 function supportsInterface( 48 bytes4 interfaceId 49 ) external pure returns (bool) { 50 return 51 interfaceId == type(IDeposit).interfaceId || 52 interfaceId == type(IERC721Receiver).interfaceId; 53 } 54 55 function deposit( 56 bytes calldata pubkey, 57 bytes calldata signature, 58 uint256 tokenID 59 ) external { 60 require(pubkey.length == 48, "Staking: invalid public key"); 61 require(signature.length == 96, "Staking: invalid signature"); 62 require( 63 T200NFT[tokenID] || T800NFT[tokenID] || T2000NFT[tokenID], 64 "Staking: not allowed token" 65 ); 66 require(depoistNFT[msg.sender] == tokenID, "Staking: tokenID do not have transfed"); 67 68 depositExpire[msg.sender] = block.timestamp + 90 days; 69 emit DepositEvent(pubkey, nftToAmount(tokenID), signature); 70 } 71 72 function withdraw() external { 73 74 uint256 tokenID = depoistNFT[msg.sender]; 75 76 require(tokenID > 0, "Staking: not deposited"); 77 require( 78 depositExpire[msg.sender] <= block.timestamp, 79 "Staking: token is locked" 80 ); 81 require( 82 token.ownerOf(tokenID) == address(this), 83 "Staking: Insuficient Allowance" 84 ); 85 86 withdrawIDToAddress[tokenID] = msg.sender; 87 withdrawAddressToID[msg.sender] = tokenID; 88 // withdrawNFT[msg.sender] = tokenID; 89 delete depoistNFT[msg.sender]; 90 delete depositExpire[msg.sender]; 91 92 emit WithdrawnEvent(nftToAmount(tokenID)); 93 } 94 95 function depositsOf(address account) external view returns (uint256) { 96 if (depositExpire[account] == 0) { 97 return 0; 98 } 99 return depoistNFT[account]; 100 } 101 102 function depositsOfBalance(address account) external view returns (uint256) { 103 if (depositExpire[account] == 0) { 104 return 0; 105 } 106 return nftToAmount(depoistNFT[account]); 107 } 108 function transferOf(address account) external view returns (uint256) { 109 return depoistNFT[account]; 110 } 111 112 function transferOfBalance(address account) external view returns (uint256) { 113 return nftToAmount(depoistNFT[account]); 114 } 115 116 function depositUnlockingTimestamp( 117 address account 118 ) external view returns (uint256) { 119 return depositExpire[account]; 120 } 121 122 function withdrawOf(address account) external view returns (uint256) { 123 return withdrawAddressToID[account]; 124 } 125 126 127 function nftToAmount(uint256 id) internal view returns (uint256) { 128 if (T200NFT[id] == true) { 129 return 200 ether; 130 } 131 132 if (T800NFT[id] == true) { 133 return 800 ether; 134 } 135 136 if (T2000NFT[id] == true) { 137 return 2000 ether; 138 } 139 140 return 0 ether; 141 } 142 143 function onERC721Received( 144 address /*operator*/, 145 address sender /*from*/, 146 uint256 tokenID /*id*/, 147 bytes calldata /*data*/ 148 ) external returns (bytes4) { 149 require( 150 T200NFT[tokenID] || T800NFT[tokenID] || T2000NFT[tokenID], 151 "Staking: not allowed token" 152 ); 153 154 // A deposit T1 , withdraw T1, A send T1 to B, B deposit T1, A deposit T2 155 if (withdrawIDToAddress[tokenID] != address(0)) { 156 address withdrawAddress = withdrawIDToAddress[tokenID]; 157 delete withdrawAddressToID[withdrawAddress]; 158 delete withdrawIDToAddress[tokenID]; 159 } 160 161 162 if (withdrawAddressToID[sender] > 0) { 163 // require( 164 // token.ownerOf(withdrawAddressToID[sender]) != address(this), 165 // "Staking: Have not withdraw" 166 // ); 167 168 uint256 withdrawTokenID = withdrawAddressToID[sender]; 169 delete withdrawAddressToID[sender]; 170 delete withdrawIDToAddress[withdrawTokenID]; 171 } 172 173 depoistNFT[sender] = tokenID; 174 return 175 bytes4( 176 keccak256( 177 "onERC721Received(address,address,uint256,bytes)" 178 ) 179 ); 180 } 181 }