update locker contract, add method: unlock from svr
This commit is contained in:
parent
8e6a76527f
commit
a2f89fa8cb
File diff suppressed because one or more lines are too long
@ -17,17 +17,20 @@ contract NFTLock is ERC721Holder, HasSignature, TimeChecker, Pausable {
|
||||
uint256 public immutable _CACHED_CHAIN_ID;
|
||||
address public immutable _CACHED_THIS;
|
||||
address public verifier;
|
||||
uint256 public maxBatch = 100;
|
||||
|
||||
struct NFTInfo {
|
||||
uint256 tokenId;
|
||||
address to;
|
||||
bool isMint;
|
||||
}
|
||||
mapping(address nft => mapping(uint256 tokenId => address user)) public lockedOriginal;
|
||||
mapping(address nft => mapping(uint256 tokenId => address user)) public passportOriginal;
|
||||
mapping(address nft => mapping(uint256 tokenId => address user)) public addressOriginal;
|
||||
mapping(address nft => mapping(address user => EnumerableSet.UintSet tokenIdSet)) private lockedRecords;
|
||||
mapping(address nft => bool status) public supportNftList;
|
||||
|
||||
event UnLock(address indexed nft, address indexed user, uint256 nonce, NFTInfo[] nftList);
|
||||
event Lock(address indexed nft, address indexed owner, address indexed to, uint256[] tokenIds);
|
||||
event Lock(address indexed nft, address indexed sender, address indexed to, uint256[] tokenIds);
|
||||
event VerifierUpdated(address indexed verifier);
|
||||
|
||||
constructor(uint256 _duration, address _verifier) TimeChecker(_duration) {
|
||||
@ -35,21 +38,25 @@ contract NFTLock is ERC721Holder, HasSignature, TimeChecker, Pausable {
|
||||
_CACHED_THIS = address(this);
|
||||
verifier = _verifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* from eoa or passport
|
||||
*/
|
||||
function lock(address nft, address to, uint256[] calldata tokenIds) external whenNotPaused{
|
||||
require(tokenIds.length <= 100, "tokenIds too many");
|
||||
require(tokenIds.length <= maxBatch, "tokenIds too many");
|
||||
require(to != address(0), "not support nft");
|
||||
require(supportNftList[nft], "not support nft");
|
||||
address owner = _msgSender();
|
||||
address _sender = _msgSender();
|
||||
for (uint256 i = 0; i < tokenIds.length; i++) {
|
||||
lockedOriginal[nft][tokenIds[i]] = to;
|
||||
passportOriginal[nft][tokenIds[i]] = to;
|
||||
addressOriginal[nft][tokenIds[i]] = _sender;
|
||||
lockedRecords[nft][to].add(tokenIds[i]);
|
||||
INFT(nft).transferFrom(owner, address(this), tokenIds[i]);
|
||||
INFT(nft).transferFrom(_sender, address(this), tokenIds[i]);
|
||||
}
|
||||
emit Lock(nft, owner, to, tokenIds);
|
||||
emit Lock(nft, _sender, to, tokenIds);
|
||||
}
|
||||
/**
|
||||
* @dev unlock or mint nft
|
||||
* from passport only
|
||||
* if tokenId not exists, mint it
|
||||
* if exists and user is owner, unlock it
|
||||
*/
|
||||
@ -59,23 +66,40 @@ contract NFTLock is ERC721Holder, HasSignature, TimeChecker, Pausable {
|
||||
uint256 signTime,
|
||||
uint256 saltNonce,
|
||||
bytes calldata signature
|
||||
) external signatureValid(signature) timeValid(signTime) whenNotPaused {
|
||||
require(nftList.length <= 100, "tokenIds too many");
|
||||
address to = _msgSender();
|
||||
bytes32 messageHash = getMessageHash(to, nft, nftList, _CACHED_THIS, _CACHED_CHAIN_ID, signTime, saltNonce);
|
||||
) external signatureValid(signature) timeValid(signTime) {
|
||||
require(nftList.length <= maxBatch, "tokenIds too many");
|
||||
address _sender = _msgSender();
|
||||
bytes32 messageHash = getMessageHash(_sender, nft, nftList, _CACHED_THIS, _CACHED_CHAIN_ID, signTime, saltNonce);
|
||||
checkSigner(verifier, messageHash, signature);
|
||||
_useSignature(signature);
|
||||
for (uint256 i = 0; i < nftList.length; i++) {
|
||||
if (nftList[i].isMint) {
|
||||
INFT(nft).mint(to, nftList[i].tokenId);
|
||||
INFT(nft).mint(nftList[i].to, nftList[i].tokenId);
|
||||
} else {
|
||||
require(lockedOriginal[nft][nftList[i].tokenId] == to, "not owner");
|
||||
delete lockedOriginal[nft][nftList[i].tokenId];
|
||||
lockedRecords[nft][to].remove(nftList[i].tokenId);
|
||||
INFT(nft).transferFrom(address(this), to, nftList[i].tokenId);
|
||||
require(passportOriginal[nft][nftList[i].tokenId] == _sender, "not owner");
|
||||
require(addressOriginal[nft][nftList[i].tokenId] == nftList[i].to, "not owner");
|
||||
delete passportOriginal[nft][nftList[i].tokenId];
|
||||
delete addressOriginal[nft][nftList[i].tokenId];
|
||||
lockedRecords[nft][_sender].remove(nftList[i].tokenId);
|
||||
INFT(nft).transferFrom(address(this), nftList[i].to, nftList[i].tokenId);
|
||||
}
|
||||
}
|
||||
emit UnLock(nft, to, saltNonce, nftList);
|
||||
emit UnLock(nft, _sender, saltNonce, nftList);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev unlock nft
|
||||
* from game svr only
|
||||
*/
|
||||
function unlockWithSvr(address nft, uint256[] calldata tokenIds) external onlyOwner(){
|
||||
require(tokenIds.length <= maxBatch, "tokenIds too many");
|
||||
for (uint256 i = 0; i < tokenIds.length; i++) {
|
||||
address _sender = addressOriginal[nft][tokenIds[i]];
|
||||
delete passportOriginal[nft][tokenIds[i]];
|
||||
delete addressOriginal[nft][tokenIds[i]];
|
||||
lockedRecords[nft][_sender].remove(tokenIds[i]);
|
||||
INFT(nft).transferFrom(address(this), _sender, tokenIds[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/** ------get------- **/
|
||||
@ -87,6 +111,10 @@ contract NFTLock is ERC721Holder, HasSignature, TimeChecker, Pausable {
|
||||
return lockedRecords[token][user].values();
|
||||
}
|
||||
|
||||
function updateBatch(uint256 _maxBatch) external onlyOwner {
|
||||
maxBatch = _maxBatch;
|
||||
}
|
||||
|
||||
function addSupportNftList(address[] calldata nftList) external onlyOwner {
|
||||
for (uint256 i = 0; i < nftList.length; i++) {
|
||||
supportNftList[nftList[i]] = true;
|
||||
@ -118,6 +146,7 @@ contract NFTLock is ERC721Holder, HasSignature, TimeChecker, Pausable {
|
||||
bytes memory encoded = abi.encodePacked(_to, _nft, _contract, _chainId, _signTime, _saltNonce);
|
||||
for (uint256 i = 0; i < _ids.length; ++i) {
|
||||
encoded = bytes.concat(encoded, abi.encodePacked(_ids[i].tokenId));
|
||||
encoded = bytes.concat(encoded, abi.encodePacked(_ids[i].to));
|
||||
encoded = bytes.concat(encoded, abi.encodePacked(_ids[i].isMint));
|
||||
}
|
||||
return keccak256(encoded);
|
||||
|
File diff suppressed because one or more lines are too long
994
deployments/imtbl_test/NFTLock.json
Normal file
994
deployments/imtbl_test/NFTLock.json
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -11,12 +11,6 @@
|
||||
"json": "assets/contracts/NFTClaimStage2.json",
|
||||
"address": "0xf45702180314187a3549FEDac3B78349b47ca6A0"
|
||||
},
|
||||
{
|
||||
"name": "NFTLock",
|
||||
"type": "logic",
|
||||
"json": "assets/contracts/NFTLock.json",
|
||||
"address": "0x59e751c2037B710090035B6ea928e0cce80aC03f"
|
||||
},
|
||||
{
|
||||
"name": "CFHero",
|
||||
"type": "erc721",
|
||||
@ -40,5 +34,11 @@
|
||||
"type": "logic",
|
||||
"json": "assets/contracts/AirdropToken.json",
|
||||
"address": "0x02B244Ba62f84ff518a4797b1859977D1fcdBBA8"
|
||||
},
|
||||
{
|
||||
"name": "NFTLock",
|
||||
"type": "logic",
|
||||
"json": "assets/contracts/NFTLock.json",
|
||||
"address": "0xc63ed18feE4C3D62b87DfCE5b5F4DafD8905D9B2"
|
||||
}
|
||||
]
|
@ -50,7 +50,7 @@ describe('NFTLock', function() {
|
||||
//@ts-ignore
|
||||
await nftLock.connect(otherAccount).lock(nft.target, owner.address, [tokenId]);
|
||||
expect(await nft.balanceOf(nftLock.target)).to.equal(1);
|
||||
expect(await nftLock.lockedOriginal(nft.target, tokenId)).to.equal(owner.address);
|
||||
expect(await nftLock.passportOriginal(nft.target, tokenId)).to.equal(owner.address);
|
||||
expect(await nft.ownerOf(tokenId)).to.equal(nftLock.target);
|
||||
});
|
||||
|
||||
@ -67,13 +67,13 @@ describe('NFTLock', function() {
|
||||
await nftLock.connect(otherAccount).lock(nft.target, owner.address, [tokenId]);
|
||||
const nonce = (Math.random() * 1000) | 0;
|
||||
const now = Date.now() / 1000 | 0;
|
||||
let localMsgHash = solidityPackedKeccak256(["address", "address", "address", "uint256", "uint256", "uint256", "uint256", "bool"],
|
||||
[owner.address, nft.target, nftLock.target, chainId, now, nonce, tokenId, false]);
|
||||
let localMsgHash = solidityPackedKeccak256(["address", "address", "address", "uint256", "uint256", "uint256", "uint256", "address", "bool"],
|
||||
[owner.address, nft.target, nftLock.target, chainId, now, nonce, tokenId, otherAccount.address, false]);
|
||||
const signature = await owner.signMessage(getBytes(localMsgHash));
|
||||
//@ts-ignore
|
||||
await nftLock.unlockOrMint(nft.target, [[tokenId, false]], now, nonce, signature);
|
||||
await nftLock.unlockOrMint(nft.target, [[tokenId, otherAccount.address, false]], now, nonce, signature);
|
||||
// await nftLock.connect(otherAccount).unlockOrMint(nft.target, [[tokenId, false]], now, nonce, signature);
|
||||
expect(await nft.ownerOf(tokenId)).to.equal(owner.address);
|
||||
expect(await nft.ownerOf(tokenId)).to.equal(otherAccount.address);
|
||||
});
|
||||
|
||||
it('should mint NFT from lock', async function() {
|
||||
@ -83,11 +83,11 @@ describe('NFTLock', function() {
|
||||
|
||||
const nonce = (Math.random() * 1000) | 0;
|
||||
const now = Date.now() / 1000 | 0;
|
||||
let localMsgHash = solidityPackedKeccak256(["address", "address", "address", "uint256", "uint256", "uint256", "uint256", "bool"],
|
||||
[otherAccount.address, nft.target, nftLock.target, chainId, now, nonce, tokenId, isMint]);
|
||||
let localMsgHash = solidityPackedKeccak256(["address", "address", "address", "uint256", "uint256", "uint256", "uint256", "address", "bool"],
|
||||
[otherAccount.address, nft.target, nftLock.target, chainId, now, nonce, tokenId, otherAccount.address, isMint]);
|
||||
const signature = await owner.signMessage(getBytes(localMsgHash));
|
||||
//@ts-ignore
|
||||
await nftLock.connect(otherAccount).unlockOrMint(nft.target, [[tokenId, isMint]], now, nonce, signature);
|
||||
await nftLock.connect(otherAccount).unlockOrMint(nft.target, [[tokenId, otherAccount.address, isMint]], now, nonce, signature);
|
||||
expect(await nft.ownerOf(tokenId)).to.equal(otherAccount.address);
|
||||
});
|
||||
|
||||
@ -98,14 +98,28 @@ describe('NFTLock', function() {
|
||||
|
||||
const nonce = (Math.random() * 1000) | 0;
|
||||
const now = Date.now() / 1000 | 0;
|
||||
let localMsgHash = solidityPackedKeccak256(["address", "address", "address", "uint256", "uint256", "uint256", "uint256", "bool"],
|
||||
[otherAccount.address, nft.target, nftLock.target, chainId, now, nonce, tokenId, isMint]);
|
||||
let localMsgHash = solidityPackedKeccak256(["address", "address", "address", "uint256", "uint256", "uint256", "uint256", "address", "bool"],
|
||||
[otherAccount.address, nft.target, nftLock.target, chainId, now, nonce, tokenId, otherAccount.address, isMint]);
|
||||
const signature = await owner.signMessage(getBytes(localMsgHash));
|
||||
//@ts-ignore
|
||||
await expect(nftLock.connect(otherAccount).unlockOrMint(nft.target, [[tokenId, isMint]], now, nonce, signature)).to.be.revertedWith(
|
||||
await expect(nftLock.connect(otherAccount).unlockOrMint(nft.target, [[tokenId, otherAccount.address, isMint]], now, nonce, signature)).to.be.revertedWith(
|
||||
"ERC721: token already minted"
|
||||
);
|
||||
});
|
||||
|
||||
it('should unlock NFT with svr', async function() {
|
||||
const { nftLock, nft, otherAccount, chainId, owner } = await loadFixture(deployOneContract);
|
||||
const tokenId = '1001'
|
||||
// @ts-ignore
|
||||
await nft.connect(otherAccount).approve(nftLock.target, tokenId);
|
||||
//@ts-ignore
|
||||
await nftLock.connect(otherAccount).lock(nft.target, owner.address, [tokenId]);
|
||||
|
||||
//@ts-ignore
|
||||
await nftLock.unlockWithSvr(nft.target, [tokenId]);
|
||||
// await nftLock.connect(otherAccount).unlockOrMint(nft.target, [[tokenId, false]], now, nonce, signature);
|
||||
expect(await nft.ownerOf(tokenId)).to.equal(otherAccount.address);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user