Skip to content

Commit

Permalink
Merge branch '119-Epic-rewards-for-bridge-validators' into 160-fee-er…
Browse files Browse the repository at this point in the history
…c-erc-posdao-chain
  • Loading branch information
patitonar committed Apr 22, 2019
2 parents d5c7c5a + c9b8a68 commit 3592024
Show file tree
Hide file tree
Showing 13 changed files with 55 additions and 47 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ sudo: required
group: beta
language: node_js
node_js:
- "9"
- "10"
cache:
yarn: true
env:
Expand Down
2 changes: 2 additions & 0 deletions contracts/upgradeable_contracts/BaseBridgeValidators.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ contract BaseBridgeValidators is EternalStorage, Ownable {

address public constant F_ADDR = 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF;

event ValidatorAdded (address indexed validator);
event ValidatorRemoved (address indexed validator);
event RequiredSignaturesChanged (uint256 requiredSignatures);

function setRequiredSignatures(uint256 _requiredSignatures)
Expand Down
4 changes: 2 additions & 2 deletions contracts/upgradeable_contracts/BasicForeignBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ contract BasicForeignBridge is EternalStorage, Validatable {
require(contractAddress == address(this));
require(!relayedMessages(txHash));
setRelayedMessages(txHash, true);
require(onExecuteMessage(recipient, amount));
require(onExecuteMessage(recipient, amount, txHash));
emit RelayedMessage(recipient, amount, txHash);
} else {
onFailedMessage(recipient, amount, txHash);
}
}

function onExecuteMessage(address, uint256) internal returns(bool);
function onExecuteMessage(address, uint256, bytes32) internal returns(bool);

function setRelayedMessages(bytes32 _txHash, bool _status) internal {
boolStorage[keccak256(abi.encodePacked("relayedMessages", _txHash))] = _status;
Expand Down
3 changes: 0 additions & 3 deletions contracts/upgradeable_contracts/BridgeValidators.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ import "./BaseBridgeValidators.sol";

contract BridgeValidators is BaseBridgeValidators {

event ValidatorAdded (address indexed validator);
event ValidatorRemoved (address indexed validator);

function initialize(
uint256 _requiredSignatures,
address[] _initialValidators,
Expand Down
9 changes: 7 additions & 2 deletions contracts/upgradeable_contracts/RewardableBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import "./FeeTypes.sol";

contract RewardableBridge is Ownable, FeeTypes {

event FeeDistributedFromAffirmation(uint256 feeAmount, bytes32 indexed transactionHash);
event FeeDistributedFromSignatures(uint256 feeAmount, bytes32 indexed transactionHash);

function _getFee(bytes32 _feeType) internal view returns(uint256) {
uint256 fee;
address feeManager = feeManagerContract();
Expand Down Expand Up @@ -70,11 +73,13 @@ contract RewardableBridge is Ownable, FeeTypes {
return fee;
}

function distributeFeeFromSignatures(uint256 _fee, address _feeManager) internal {
function distributeFeeFromSignatures(uint256 _fee, address _feeManager, bytes32 _txHash) internal {
require(_feeManager.delegatecall(abi.encodeWithSignature("distributeFeeFromSignatures(uint256)", _fee)));
emit FeeDistributedFromSignatures(_fee, _txHash);
}

function distributeFeeFromAffirmation(uint256 _fee, address _feeManager) internal {
function distributeFeeFromAffirmation(uint256 _fee, address _feeManager, bytes32 _txHash) internal {
require(_feeManager.delegatecall(abi.encodeWithSignature("distributeFeeFromAffirmation(uint256)", _fee)));
emit FeeDistributedFromAffirmation(_fee, _txHash);
}
}
9 changes: 3 additions & 6 deletions contracts/upgradeable_contracts/RewardableValidators.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ import "./BaseBridgeValidators.sol";

contract RewardableValidators is BaseBridgeValidators {

event ValidatorAdded (address indexed validator, address reward);
event ValidatorRemoved (address indexed validator);

function initialize(
uint256 _requiredSignatures,
address[] _initialValidators,
Expand Down Expand Up @@ -43,7 +40,7 @@ contract RewardableValidators is BaseBridgeValidators {

setValidatorCount(validatorCount().add(1));
setValidatorRewardAddress(_initialValidators[i], _initialRewards[i]);
emit ValidatorAdded(_initialValidators[i], _initialRewards[i]);
emit ValidatorAdded(_initialValidators[i]);
}

uintStorage[keccak256(abi.encodePacked("requiredSignatures"))] = _requiredSignatures;
Expand All @@ -54,11 +51,11 @@ contract RewardableValidators is BaseBridgeValidators {
return isInitialized();
}

function addValidator(address _validator, address _reward) external onlyOwner {
function addRewardableValidator(address _validator, address _reward) external onlyOwner {
require(_reward != address(0));
_addValidator(_validator);
setValidatorRewardAddress(_validator, _reward);
emit ValidatorAdded(_validator, _reward);
emit ValidatorAdded(_validator);
}

function removeValidator(address _validator) external onlyOwner {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ contract ForeignBridgeErcToErc is BasicBridge, BasicForeignBridge {
return ERC20Basic(addressStorage[keccak256(abi.encodePacked("erc20token"))]);
}

function onExecuteMessage(address _recipient, uint256 _amount) internal returns(bool){
function onExecuteMessage(address _recipient, uint256 _amount, bytes32 _txHash) internal returns(bool){
setTotalExecutedPerDay(getCurrentDay(), totalExecutedPerDay(getCurrentDay()).add(_amount));
return erc20token().transfer(_recipient, _amount);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ contract ForeignBridgeErcToNative is BasicBridge, BasicForeignBridge {
return ERC20Basic(addressStorage[keccak256(abi.encodePacked("erc20token"))]);
}

function onExecuteMessage(address _recipient, uint256 _amount) internal returns(bool) {
function onExecuteMessage(address _recipient, uint256 _amount, bytes32 _txHash) internal returns(bool) {
setTotalExecutedPerDay(getCurrentDay(), totalExecutedPerDay(getCurrentDay()).add(_amount));
return erc20token().transfer(_recipient, _amount);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ import "./RewardableHomeBridgeErcToNative.sol";
contract HomeBridgeErcToNative is EternalStorage, BasicBridge, BasicHomeBridge, OverdrawManagement, RewardableHomeBridgeErcToNative {

event AmountLimitExceeded(address recipient, uint256 value, bytes32 transactionHash);
event FeeDistributedFromAffirmation(uint256 feeAmount, bytes32 indexed transactionHash);
event FeeDistributedFromSignatures(uint256 feeAmount, bytes32 indexed transactionHash);

function () public payable {
require(msg.value > 0);
Expand Down Expand Up @@ -162,9 +160,8 @@ contract HomeBridgeErcToNative is EternalStorage, BasicBridge, BasicHomeBridge,
address feeManager = feeManagerContract();
if (feeManager != address(0)) {
uint256 fee = calculateFee(valueToMint, false, feeManager, FOREIGN_FEE);
distributeFeeFromAffirmation(fee, feeManager);
distributeFeeFromAffirmation(fee, feeManager, txHash);
valueToMint = valueToMint.sub(fee);
emit FeeDistributedFromAffirmation(fee, txHash);
}
blockReward.addExtraReceiver(valueToMint, _recipient);
return true;
Expand All @@ -179,8 +176,7 @@ contract HomeBridgeErcToNative is EternalStorage, BasicBridge, BasicHomeBridge,
address contractAddress;
(recipient, amount, txHash, contractAddress) = Message.parseMessage(_message);
uint256 fee = calculateFee(amount, true, feeManager, HOME_FEE);
distributeFeeFromSignatures(fee, feeManager);
emit FeeDistributedFromSignatures(fee, txHash);
distributeFeeFromSignatures(fee, feeManager, txHash);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,13 @@ contract ForeignBridgeNativeToErc is ERC677Receiver, BasicBridge, BasicForeignBr
setOwner(_owner);
}

function onExecuteMessage(address _recipient, uint256 _amount) internal returns(bool) {
function onExecuteMessage(address _recipient, uint256 _amount, bytes32 _txHash) internal returns(bool) {
setTotalExecutedPerDay(getCurrentDay(), totalExecutedPerDay(getCurrentDay()).add(_amount));
uint256 valueToMint = _amount;
address feeManager = feeManagerContract();
if (feeManager != address(0)) {
uint256 fee = calculateFee(valueToMint, false, feeManager, HOME_FEE);
distributeFeeFromSignatures(fee, feeManager);
distributeFeeFromSignatures(fee, feeManager, _txHash);
valueToMint = valueToMint.sub(fee);
}
return erc677token().mint(_recipient, valueToMint);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import "../Sacrifice.sol";

contract HomeBridgeNativeToErc is EternalStorage, BasicBridge, BasicHomeBridge, RewardableHomeBridgeNativeToErc {

event FeeDistributedFromAffirmation(uint256 feeAmount, bytes32 indexed transactionHash);

function () public payable {
require(msg.value > 0);
require(msg.data.length == 0);
Expand Down Expand Up @@ -121,9 +119,8 @@ contract HomeBridgeNativeToErc is EternalStorage, BasicBridge, BasicHomeBridge,
address feeManager = feeManagerContract();
if (feeManager != address(0)) {
uint256 fee = calculateFee(valueToTransfer, false, feeManager, FOREIGN_FEE);
distributeFeeFromAffirmation(fee, feeManager);
distributeFeeFromAffirmation(fee, feeManager, txHash);
valueToTransfer = valueToTransfer.sub(fee);
emit FeeDistributedFromAffirmation(fee, txHash);
}

if (!_recipient.send(valueToTransfer)) {
Expand Down
35 changes: 23 additions & 12 deletions test/native_to_erc/foreign_bridge_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -623,10 +623,14 @@ contract('ForeignBridge', async (accounts) => {
const vrs = signatureToVRS(signature);

const { logs } = await foreignBridge.executeSignatures([vrs.v], [vrs.r], [vrs.s], message).should.be.fulfilled
logs[0].event.should.be.equal("RelayedMessage")
logs[0].args.recipient.should.be.equal(recipientAccount)
logs[0].args.value.should.be.bignumber.equal(value)
logs[0].args.transactionHash.should.be.equal(transactionHash);

logs[0].event.should.be.equal("FeeDistributedFromSignatures")
logs[0].args.should.be.deep.equal({feeAmount, transactionHash})

logs[1].event.should.be.equal("RelayedMessage")
logs[1].args.recipient.should.be.equal(recipientAccount)
logs[1].args.value.should.be.bignumber.equal(value)
logs[1].args.transactionHash.should.be.equal(transactionHash);

const balanceAfter = await token.balanceOf(recipientAccount);
const totalSupplyAfter = await token.totalSupply();
Expand All @@ -643,6 +647,7 @@ contract('ForeignBridge', async (accounts) => {
const feePerValidator = web3.toBigNumber(166666666666666)
const feePerValidatorPlusDiff = web3.toBigNumber(166666666666668)
const value = halfEther
const feeAmount = value.mul(web3.toBigNumber(fee));
const finalUserValue = value.mul(web3.toBigNumber(1-fee));

const validators = [accounts[1], accounts[2], accounts[3]]
Expand Down Expand Up @@ -673,10 +678,13 @@ contract('ForeignBridge', async (accounts) => {
const { logs } = await foreignBridge.executeSignatures([vrs.v, vrs2.v, vrs3.v], [vrs.r, vrs2.r, vrs3.r], [vrs.s, vrs2.s, vrs3.s], message).should.be.fulfilled

// Then
logs[0].event.should.be.equal("RelayedMessage")
logs[0].args.recipient.should.be.equal(recipientAccount)
logs[0].args.value.should.be.bignumber.equal(value)
logs[0].args.transactionHash.should.be.equal(transactionHash);
logs[0].event.should.be.equal("FeeDistributedFromSignatures")
logs[0].args.should.be.deep.equal({feeAmount, transactionHash})

logs[1].event.should.be.equal("RelayedMessage")
logs[1].args.recipient.should.be.equal(recipientAccount)
logs[1].args.value.should.be.bignumber.equal(value)
logs[1].args.transactionHash.should.be.equal(transactionHash);

const balanceAfter = await token.balanceOf(recipientAccount);
const totalSupplyAfter = await token.totalSupply();
Expand Down Expand Up @@ -736,10 +744,13 @@ contract('ForeignBridge', async (accounts) => {
const { logs } = await foreignBridge.executeSignatures([vrs.v, vrs2.v, vrs3.v], [vrs.r, vrs2.r, vrs3.r], [vrs.s, vrs2.s, vrs3.s], message).should.be.fulfilled

// Then
logs[0].event.should.be.equal("RelayedMessage")
logs[0].args.recipient.should.be.equal(recipientAccount)
logs[0].args.value.should.be.bignumber.equal(value)
logs[0].args.transactionHash.should.be.equal(transactionHash);
logs[0].event.should.be.equal("FeeDistributedFromSignatures")
logs[0].args.should.be.deep.equal({feeAmount, transactionHash})

logs[1].event.should.be.equal("RelayedMessage")
logs[1].args.recipient.should.be.equal(recipientAccount)
logs[1].args.value.should.be.bignumber.equal(value)
logs[1].args.transactionHash.should.be.equal(transactionHash);

const balanceAfter = await token.balanceOf(recipientAccount);
const totalSupplyAfter = await token.totalSupply();
Expand Down
17 changes: 10 additions & 7 deletions test/rewardable_validators_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,31 +53,34 @@ contract('RewardableValidators', async (accounts) => {
let newReward = accounts[5];

false.should.be.equal(await bridgeValidators.isValidator(newValidator))
await bridgeValidators.addValidator(newValidator, newReward, {from: validators[0]}).should.be.rejectedWith(ERROR_MSG)
const {logs} = await bridgeValidators.addValidator(newValidator, newReward, {from: owner}).should.be.fulfilled
await bridgeValidators.addRewardableValidator(newValidator, newReward, {from: validators[0]}).should.be.rejectedWith(ERROR_MSG)
const {logs} = await bridgeValidators.addRewardableValidator(newValidator, newReward, {from: owner}).should.be.fulfilled
true.should.be.equal(await bridgeValidators.isValidator(newValidator))
'3'.should.be.bignumber.equal(await bridgeValidators.validatorCount())
logs[0].event.should.be.equal('ValidatorAdded')
logs[0].args.should.be.deep.equal({ validator: newValidator, reward: newReward })
logs[0].args.should.be.deep.equal({ validator: newValidator })

const rewardAddress = await bridgeValidators.getValidatorRewardAddress(newValidator)
rewardAddress.should.be.equal(newReward)
})

it('cannot add already existing validator', async () => {
true.should.be.equal(await bridgeValidators.isValidator(validators[0]))
await bridgeValidators.addValidator(validators[0], rewards[0], {from: owner}).should.be.rejectedWith(ERROR_MSG)
await bridgeValidators.addRewardableValidator(validators[0], rewards[0], {from: owner}).should.be.rejectedWith(ERROR_MSG)
'2'.should.be.bignumber.equal(await bridgeValidators.validatorCount())
})

it(`cannot add 0xf as validator address`, async () => {
// Given
await bridgeValidators.addValidator(F_ADDRESS, rewards[0], { from: owner }).should.be.rejectedWith(ERROR_MSG)
await bridgeValidators.addRewardableValidator(F_ADDRESS, rewards[0], { from: owner }).should.be.rejectedWith(ERROR_MSG)
})

it(`cannot add 0x0 as validator address`, async () => {
await bridgeValidators.addValidator(ZERO_ADDRESS, rewards[0], {from: owner}).should.be.rejectedWith(ERROR_MSG)
await bridgeValidators.addRewardableValidator(ZERO_ADDRESS, rewards[0], {from: owner}).should.be.rejectedWith(ERROR_MSG)
})

it(`cannot add 0x0 as reward address`, async () => {
await bridgeValidators.addValidator(accounts[4], ZERO_ADDRESS, { from: owner }).should.be.rejectedWith(ERROR_MSG)
await bridgeValidators.addRewardableValidator(accounts[4], ZERO_ADDRESS, { from: owner }).should.be.rejectedWith(ERROR_MSG)
})
})

Expand Down

0 comments on commit 3592024

Please sign in to comment.