diff --git a/contracts/schemes/ExternalLocking4Reputation.sol b/contracts/schemes/ExternalLocking4Reputation.sol index 92958460..dd004bbb 100644 --- a/contracts/schemes/ExternalLocking4Reputation.sol +++ b/contracts/schemes/ExternalLocking4Reputation.sol @@ -10,20 +10,24 @@ import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; contract ExternalLocking4Reputation is Locking4Reputation, Ownable { + event Register(address indexed _beneficiary); + address public externalLockingContract; string public getBalanceFuncSignature; // locker -> bool mapping(address => bool) public externalLockers; + // beneficiary -> bool + mapping(address => bool) public registrar; /** * @dev initialize * @param _avatar the avatar to mint reputation from * @param _reputationReward the total reputation this contract will reward * for the token locking - * @param _lockingStartTime locking starting period time. - * @param _lockingEndTime the locking end time. - * locking is disable after this time. + * @param _claimingStartTime claiming starting period time. + * @param _claimingEndTime the claiming end time. + * claiming is disable after this time. * @param _redeemEnableTime redeem enable time . * redeem reputation can be done after this time. * @param _externalLockingContract the contract which lock the token. @@ -33,36 +37,45 @@ contract ExternalLocking4Reputation is Locking4Reputation, Ownable { function initialize( Avatar _avatar, uint _reputationReward, - uint _lockingStartTime, - uint _lockingEndTime, + uint _claimingStartTime, + uint _claimingEndTime, uint _redeemEnableTime, address _externalLockingContract, string _getBalanceFuncSignature) external onlyOwner { - require(_lockingEndTime > _lockingStartTime, "_lockingEndTime should be greater than _lockingStartTime"); + require(_claimingEndTime > _claimingStartTime, "_claimingEndTime should be greater than _claimingStartTime"); externalLockingContract = _externalLockingContract; getBalanceFuncSignature = _getBalanceFuncSignature; super._initialize( _avatar, _reputationReward, - _lockingStartTime, - _lockingEndTime, + _claimingStartTime, + _claimingEndTime, _redeemEnableTime, 1); } /** - * @dev lock function - * @return lockingId + * @dev claim function + * @param _beneficiary the beneficiary address to claim for + * if _beneficiary == 0 the claim will be for the msg.sender. + * @return claimId */ - function lock() public returns(bytes32) { + function claim(address _beneficiary) public returns(bytes32) { require(avatar != Avatar(0), "should initialize first"); - require(externalLockers[msg.sender] == false, "locking twice is not allowed"); - externalLockers[msg.sender] = true; + address beneficiary; + if (_beneficiary == address(0)) { + beneficiary = msg.sender; + } else { + require(registrar[_beneficiary],"beneficiary should be register"); + beneficiary = _beneficiary; + } + require(externalLockers[beneficiary] == false, "claiming twice is not allowed"); + externalLockers[beneficiary] = true; // solium-disable-next-line security/no-low-level-calls - bool result = externalLockingContract.call(abi.encodeWithSignature(getBalanceFuncSignature, msg.sender)); + bool result = externalLockingContract.call(abi.encodeWithSignature(getBalanceFuncSignature, beneficiary)); uint lockedAmount; // solium-disable-next-line security/no-inline-assembly assembly { @@ -73,6 +86,15 @@ contract ExternalLocking4Reputation is Locking4Reputation, Ownable { default { lockedAmount := mload(0) } } - return super._lock(lockedAmount, 1, msg.sender); + return super._lock(lockedAmount, 1, beneficiary); + } + + /** + * @dev register function + * register for external locking claim + */ + function register() public { + registrar[msg.sender] = true; + emit Register(msg.sender); } } diff --git a/test/externallocking4reputation.js b/test/externallocking4reputation.js index 974a8e05..ef0a0e9f 100644 --- a/test/externallocking4reputation.js +++ b/test/externallocking4reputation.js @@ -5,14 +5,14 @@ const constants = require('./constants'); var ExternalLocking4Reputation = artifacts.require("./ExternalLocking4Reputation.sol"); var ExternalTokenLockerMock = artifacts.require("./ExternalTokenLockerMock.sol"); -const setup = async function (accounts,_repAllocation = 100,_lockingStartTime = 0,_lockingEndTime = 3000,_redeemEnableTime = 3000,_initialize = true) { +const setup = async function (accounts,_repAllocation = 100,_claimingStartTime = 0,_claimingEndTime = 3000,_redeemEnableTime = 3000,_initialize = true) { var testSetup = new helpers.TestSetup(); var controllerCreator = await ControllerCreator.new({gas: constants.ARC_GAS_LIMIT}); testSetup.daoCreator = await DaoCreator.new(controllerCreator.address,{gas:constants.ARC_GAS_LIMIT}); testSetup.org = await helpers.setupOrganization(testSetup.daoCreator,accounts[0],1000,1000); var block = await web3.eth.getBlock("latest"); - testSetup.lockingEndTime = block.timestamp + _lockingEndTime; - testSetup.lockingStartTime = block.timestamp + _lockingStartTime; + testSetup.lockingEndTime = block.timestamp + _claimingEndTime; + testSetup.lockingStartTime = block.timestamp + _claimingStartTime; testSetup.redeemEnableTime = block.timestamp + _redeemEnableTime; testSetup.extetnalTokenLockerMock = await ExternalTokenLockerMock.new(); await testSetup.extetnalTokenLockerMock.lock(100,{from:accounts[0]}); @@ -46,9 +46,9 @@ contract('ExternalLocking4Reputation', accounts => { assert.equal(await testSetup.externalLocking4Reputation.getBalanceFuncSignature(),"lockedTokenBalances(address)"); }); - it("lock", async () => { + it("claim", async () => { let testSetup = await setup(accounts); - var tx = await testSetup.externalLocking4Reputation.lock(); + var tx = await testSetup.externalLocking4Reputation.claim(helpers.NULL_ADDRESS); var lockingId = await helpers.getValueFromLogs(tx, '_lockingId',1); assert.equal(tx.logs.length,1); assert.equal(tx.logs[0].event,"Lock"); @@ -58,52 +58,79 @@ contract('ExternalLocking4Reputation', accounts => { assert.equal(tx.logs[0].args._locker,accounts[0]); }); - it("cannot lock before set parameters", async () => { + it("claim on behalf of a beneficiary", async () => { + let testSetup = await setup(accounts); + var tx = await testSetup.externalLocking4Reputation.register({from:accounts[1]}); + assert.equal(tx.logs.length,1); + assert.equal(tx.logs[0].event,"Register"); + assert.equal(tx.logs[0].args._beneficiary,accounts[1]); + tx = await testSetup.externalLocking4Reputation.claim(accounts[1]); + var lockingId = await helpers.getValueFromLogs(tx, '_lockingId',1); + assert.equal(tx.logs.length,1); + assert.equal(tx.logs[0].event,"Lock"); + assert.equal(tx.logs[0].args._lockingId,lockingId); + assert.equal(tx.logs[0].args._amount,200); + assert.equal(tx.logs[0].args._period,1); + assert.equal(tx.logs[0].args._locker,accounts[1]); + }); + + it("cannot claim on behalf of a beneficiary if not register", async () => { + let testSetup = await setup(accounts); + try { + await testSetup.externalLocking4Reputation.claim(accounts[1]); + assert(false, "cannot claim on behalf of a beneficiary if not register"); + } catch(error) { + helpers.assertVMException(error); + } + }); + + + it("cannot claim before set parameters", async () => { let testSetup = await setup(accounts,100,0,3000,3000,false); try { - await testSetup.externalLocking4Reputation.lock(); + await testSetup.externalLocking4Reputation.claim(helpers.NULL_ADDRESS); assert(false, "cannot lock before set parameters"); } catch(error) { helpers.assertVMException(error); } }); - it("lock with value == 0 should revert", async () => { + it("claim with value == 0 should revert", async () => { let testSetup = await setup(accounts); try { - await testSetup.externalLocking4Reputation.lock({from:accounts[4]}); + await testSetup.externalLocking4Reputation.claim(helpers.NULL_ADDRESS,{from:accounts[4]}); assert(false, "lock with value == 0 should revert"); } catch(error) { helpers.assertVMException(error); } }); - it("lock after _lockingEndTime should revert", async () => { + it("claim after _claimingEndTime should revert", async () => { let testSetup = await setup(accounts); await helpers.increaseTime(3001); try { - await testSetup.externalLocking4Reputation.lock(); - assert(false, "lock after _lockingEndTime should revert"); + await testSetup.externalLocking4Reputation.claim(helpers.NULL_ADDRESS); + assert(false, "lock after _claimingEndTime should revert"); } catch(error) { helpers.assertVMException(error); } }); - it("lock before start should revert", async () => { + it("claim before start should revert", async () => { let testSetup = await setup(accounts,100,100); try { - await testSetup.externalLocking4Reputation.lock(); + await testSetup.externalLocking4Reputation.claim(helpers.NULL_ADDRESS); assert(false, "lock before start should revert"); } catch(error) { helpers.assertVMException(error); } }); - it("cannot lock twice for the same user", async () => { + it("cannot claim twice for the same user", async () => { let testSetup = await setup(accounts); - await testSetup.externalLocking4Reputation.lock(); + await testSetup.externalLocking4Reputation.claim(helpers.NULL_ADDRESS); try { - await testSetup.externalLocking4Reputation.lock(); + await testSetup.externalLocking4Reputation.claim(helpers.NULL_ADDRESS); assert(false, "cannot lock twice for the same user"); } catch(error) { helpers.assertVMException(error); @@ -112,7 +139,7 @@ contract('ExternalLocking4Reputation', accounts => { it("redeem", async () => { let testSetup = await setup(accounts); - var tx = await testSetup.externalLocking4Reputation.lock(); + var tx = await testSetup.externalLocking4Reputation.claim(helpers.NULL_ADDRESS); await helpers.increaseTime(3001); tx = await testSetup.externalLocking4Reputation.redeem(accounts[0]); assert.equal(tx.logs.length,1); @@ -124,8 +151,8 @@ contract('ExternalLocking4Reputation', accounts => { it("redeem score ", async () => { let testSetup = await setup(accounts); - await testSetup.externalLocking4Reputation.lock({from:accounts[0]}); - await testSetup.externalLocking4Reputation.lock({from:accounts[2]}); + await testSetup.externalLocking4Reputation.claim(helpers.NULL_ADDRESS,{from:accounts[0]}); + await testSetup.externalLocking4Reputation.claim(helpers.NULL_ADDRESS,{from:accounts[2]}); await helpers.increaseTime(3001); await testSetup.externalLocking4Reputation.redeem(accounts[0]); await testSetup.externalLocking4Reputation.redeem(accounts[2]); @@ -135,7 +162,7 @@ contract('ExternalLocking4Reputation', accounts => { it("redeem cannot redeem twice", async () => { let testSetup = await setup(accounts); - await testSetup.externalLocking4Reputation.lock(); + await testSetup.externalLocking4Reputation.claim(helpers.NULL_ADDRESS); await helpers.increaseTime(3001); await testSetup.externalLocking4Reputation.redeem(accounts[0]); try { @@ -148,7 +175,7 @@ contract('ExternalLocking4Reputation', accounts => { it("redeem before lockingEndTime should revert", async () => { let testSetup = await setup(accounts); - await testSetup.externalLocking4Reputation.lock(); + await testSetup.externalLocking4Reputation.claim(helpers.NULL_ADDRESS); await helpers.increaseTime(50); try { await testSetup.externalLocking4Reputation.redeem(accounts[0]); @@ -160,7 +187,7 @@ contract('ExternalLocking4Reputation', accounts => { it("redeem before redeemEnableTime should revert", async () => { let testSetup = await setup(accounts,100,0,3000,4000,true); - await testSetup.externalLocking4Reputation.lock(); + await testSetup.externalLocking4Reputation.claim(helpers.NULL_ADDRESS); await helpers.increaseTime(3500); try { await testSetup.externalLocking4Reputation.redeem(accounts[0]);