diff --git a/contracts/contribute/ContributeManager.sol b/contracts/contribute/ContributeManager.sol index 01df8b8..dbb074c 100644 --- a/contracts/contribute/ContributeManager.sol +++ b/contracts/contribute/ContributeManager.sol @@ -213,7 +213,7 @@ contract ContributeManager is ERC721TokenReceiver { } // Check for existing service corresponding to the msg.sender - (, uint256 serviceId, address multisig, ) = IContributors(contributorsProxy).mapSocialIdServiceInfo(msg.sender); + (, uint256 serviceId, address multisig, ) = IContributors(contributorsProxy).mapAccountServiceInfo(msg.sender); if (serviceId > 0) { revert ServiceAlreadyStaked(socialId, serviceId, multisig); } @@ -273,7 +273,7 @@ contract ContributeManager is ERC721TokenReceiver { _locked = 2; // Check for existing service corresponding to the msg.sender - (, uint256 serviceIdCheck, address multisig, ) = IContributors(contributorsProxy).mapSocialIdServiceInfo(msg.sender); + (, uint256 serviceIdCheck, address multisig, ) = IContributors(contributorsProxy).mapAccountServiceInfo(msg.sender); if (serviceIdCheck > 0) { revert ServiceAlreadyStaked(socialId, serviceIdCheck, multisig); } @@ -289,7 +289,7 @@ contract ContributeManager is ERC721TokenReceiver { } // Transfer the service NFT - IToken(serviceRegistry).transferFrom(msg.sender, address(this), serviceId); + INFToken(serviceRegistry).safeTransferFrom(msg.sender, address(this), serviceId); // Stake the service _stake(socialId, serviceId, multisig, stakingInstance); @@ -309,7 +309,7 @@ contract ContributeManager is ERC721TokenReceiver { // Check for existing service corresponding to the social Id (uint256 socialId, uint256 serviceId, address multisig, address stakingInstance) = - IContributors(contributorsProxy).mapSocialIdServiceInfo(msg.sender); + IContributors(contributorsProxy).mapAccountServiceInfo(msg.sender); if (serviceId == 0) { revert ServiceNotDefined(socialId); } @@ -318,7 +318,7 @@ contract ContributeManager is ERC721TokenReceiver { IStaking(stakingInstance).unstake(serviceId); // Transfer the service back to the original owner - IToken(serviceRegistry).transfer(msg.sender, serviceId); + INFToken(serviceRegistry).transferFrom(address(this), msg.sender, serviceId); // Zero the service info: the service is out of the contribute records, however multisig activity is still valid // If the same service is staked back, the multisig activity continues being tracked @@ -340,7 +340,7 @@ contract ContributeManager is ERC721TokenReceiver { // Check for existing service corresponding to the social Id (uint256 socialId, uint256 serviceId, address multisig, address stakingInstance) = - IContributors(contributorsProxy).mapSocialIdServiceInfo(msg.sender); + IContributors(contributorsProxy).mapAccountServiceInfo(msg.sender); if (serviceId == 0) { revert ServiceNotDefined(socialId); } diff --git a/contracts/contribute/Contributors.sol b/contracts/contribute/Contributors.sol index ef8a8ca..8509b1b 100644 --- a/contracts/contribute/Contributors.sol +++ b/contracts/contribute/Contributors.sol @@ -60,8 +60,8 @@ contract Contributors { // Service manager contract address address public manager; - // Mapping of address => service info - mapping(address => ServiceInfo) public mapSocialIdServiceInfo; + // Mapping of account address => service info + mapping(address => ServiceInfo) public mapAccountServiceInfo; // Mapping of service multisig address => activity mapping(address => uint256) public mapMutisigActivities; // Mapping of whitelisted contributor agents @@ -151,7 +151,7 @@ contract Contributors { } // Set (or remove) multisig for the corresponding social id - ServiceInfo storage serviceInfo = mapSocialIdServiceInfo[serviceOwner]; + ServiceInfo storage serviceInfo = mapAccountServiceInfo[serviceOwner]; serviceInfo.socialId = socialId; serviceInfo.serviceId = serviceId; serviceInfo.multisig = multisig; diff --git a/contracts/contribute/interfaces/IContributors.sol b/contracts/contribute/interfaces/IContributors.sol index 6287c35..ac0e5c6 100644 --- a/contracts/contribute/interfaces/IContributors.sol +++ b/contracts/contribute/interfaces/IContributors.sol @@ -17,12 +17,12 @@ interface IContributors { address stakingInstance ) external; - /// @dev Gets service info corresponding to a specified social Id. + /// @dev Gets service info corresponding to a specified service owner. /// @param serviceOwner Service owner. /// @return socialId Social Id. /// @return serviceId Corresponding service Id. /// @return multisig Corresponding service multisig. /// @return stakingInstance Staking instance address. - function mapSocialIdServiceInfo(address serviceOwner) external view + function mapAccountServiceInfo(address serviceOwner) external view returns (uint256 socialId, uint256 serviceId, address multisig, address stakingInstance); } diff --git a/contracts/contribute/interfaces/IToken.sol b/contracts/contribute/interfaces/IToken.sol index 0eb651e..b17a335 100644 --- a/contracts/contribute/interfaces/IToken.sol +++ b/contracts/contribute/interfaces/IToken.sol @@ -29,4 +29,16 @@ interface INFToken { /// @param spender Account address that will be able to transfer the token on behalf of the caller. /// @param id Token id. function approve(address spender, uint256 id) external; + + /// @dev Transfers a specified token Id. + /// @param from Account address to transfer from. + /// @param to Account address to transfer to. + /// @param id Token id. + function transferFrom(address from, address to, uint256 id) external; + + /// @dev Transfers a specified token Id with a callback. + /// @param from Account address to transfer from. + /// @param to Account address to transfer to. + /// @param id Token id. + function safeTransferFrom(address from, address to, uint256 id) external; } \ No newline at end of file diff --git a/test/StakingContribute.js b/test/StakingContribute.js index 1ab88cb..1df76ee 100644 --- a/test/StakingContribute.js +++ b/test/StakingContribute.js @@ -155,7 +155,10 @@ describe("Staking", function () { await serviceRegistry.changeMultisigPermission(gnosisSafeMultisig.address, true); // Set the manager of contributorsProxy - contributors.changeManager(contributeManager.address); + await contributors.changeManager(contributeManager.address); + + // Set deployer address to be the agent + await contributors.setContributeAgentStatuses([deployer.address], [true]); // Fund the staking contract await token.approve(stakingTokenAddress, ethers.utils.parseEther("1")); @@ -166,10 +169,67 @@ describe("Staking", function () { }); context("Contribute manager", function () { - it.only("Mint and stake", async function () { + it("Mint and stake", async function () { + // Approve OLAS for contributeManager + await token.approve(contributeManager.address, serviceParams.minStakingDeposit * 2); + + // Mint and stake the service + await contributeManager.createAndStake(socialId, stakingToken.address, {value: 2}); + }); + + it("Mint, stake, unstake and stake again", async function () { + // Take a snapshot of the current state of the blockchain + const snapshot = await helpers.takeSnapshot(); + + // Approve OLAS for contributeManager + await token.approve(contributeManager.address, serviceParams.minStakingDeposit * 2); + + // Mint and stake the service + await contributeManager.createAndStake(socialId, stakingToken.address, {value: 2}); + + // Increase the time while the service does not reach the required amount of transactions per second (TPS) + await helpers.time.increase(maxInactivity); + + // Unstake the service + await contributeManager.unstake(); + + // Approve the service for the contributeManager + await serviceRegistry.approve(contributeManager.address, serviceId); + + // Stake the service again + await contributeManager.stake(socialId, serviceId, stakingToken.address); + + // Restore a previous state of blockchain + snapshot.restore(); + }); + + it("Mint, stake, perform activity, claim", async function () { + // Take a snapshot of the current state of the blockchain + const snapshot = await helpers.takeSnapshot(); + + // Approve OLAS for contributeManager await token.approve(contributeManager.address, serviceParams.minStakingDeposit * 2); + // Mint and stake the service await contributeManager.createAndStake(socialId, stakingToken.address, {value: 2}); + + // Get the user data + const serviceInfo = await contributors.mapAccountServiceInfo(deployer.address); + + // Perform the service activity + await contributors.increaseActivity([serviceInfo.multisig], [10]); + + // Increase the time until the next staking epoch + await helpers.time.increase(livenessPeriod); + + // Call the checkpoint + await stakingToken.checkpoint(); + + // Claim rewards + await contributeManager.claim(); + + // Restore a previous state of blockchain + snapshot.restore(); }); }); });