Skip to content

Commit

Permalink
RewardEscrowV2 L2 integration (1st iteration) (#967)
Browse files Browse the repository at this point in the history
* Sending rewards into L2

* Fixing broken parts

* Unit tests

* New unit tests

* Adding coverage for migrate

* Remove duplicate tests

* Use smock to test L2 contracts (#820)

* Remove MintableSynthetixMock.sol

* Remove test:multi (implemented in external PR)

* Remove secondary contract refs (#823)

* New messenger interface (#825)

* Add initial tests

* Add loop for initializing the array

* Add test for importVestingEntries()

* Comment  out expected data tests

* Import new IRewardEscrowV2 interface

* Fix SynthetixBridgeToOptimism unit tests

* Fix SynthetixBridgeToBase unit tests

* Add more tests

* Use V2 suffix for rewardEscrow view function

* Add RewardEscrowV2 for  mocking

* Minor fix

* Adds a new script to connect l2 bridge (#894)

* Adds a new script to connect l2 bridge

* Bugfix on new command

* Skip vsynth prod test (#895)

* Adds a --clean-build flag to the build command (#896)

* Fix lint pre-commit hook (#900)

* Disable etherscan checks in CI (#897)

* Skip vsynth prod test (#902)

* Adds a few options to connect-bridge (#906)

* Adds a few options to connect-bridge

* Fix connect-bridge pks

* Minor fix

* Another minor fix

* Fix

* Logging more output

* Fix

* Fix

* Fixing prod test for vSynth and verifying more rinkeby contracts in etherscan

* remove aggregator feed for BCH prices (#905)

* Prepublish step

* 2.32.2-sip-95-remove-BCH-aggregator

* Prepublish step

* 2.32.3

* Develop - Merge master into develop (#911)

* Address list renamed to address set and make adding elements idempotent. (#917)

* Preparations for L2 Phase C deployment (#901)

* Improved lint pre-commit hook (#918)

* Build circleci config with Mustache (#883)

* L2 Phase C Release (#919)

* Prepublish step

* 2.33.0-ovm

* Updating versions for ovm

* Add circleci paths to prettierignore for pretty-quick (#921)

* Do not ignore dotfiles in js linter (#923)

* reset iETH prices (#922)

* reset iETH prices

* update StakingRewardsiETH address and ABI

* merge master into develop (#926)


* reset iETH prices (#922) and update StakingRewardsiETH address and ABI

Co-authored-by: Alejandro Santander <Palebluedot@gmail.com>
Co-authored-by: justin j. moses <justinjmoses@gmail.com>
Co-authored-by: Synthetix Team <team@synthetix.io>

* Prepublish step

* 2.33.1

* Added dockerhub authetication to circleci (#924)

* Improved connect-bridge script (#928)

* Use new rewardEscrowV2

* Modify burnForMigration() to return a strcut array

* Use structs to avoid stack too deep errors

* Use new interface

* Use new importedVestingEntries() and fix unit tests

* sip99 (#936)

* Prepublish step

* 2.33.2

* sip 98 double swing trade exchange fees (#935)

* update calculation of exchangeFeeRate for swing trades from long <-> short synths without sUSD step

* fix audit findings on missing exchangeFeeRate assignment and update Exchanger tests

* release adhara 2.33.0 adhara (#939)

* release adhara kovan 2.33.0

* release Exchanger 2.33.0 Adhara to mainnet

* Prepublish step

* 2.33.0

* Prepublish step

* 2.34.0

* Version fix for master along with some fork fixes (#941)

* Fixing versions

* merge 2.34.0 release into develop (#940)

* Add 0-debt requirement for withdrawals (#942)

* Deploy bug fix: adding synths (#920)

* Deployed fix for SynthetixBridgeToBase (#945)

* Prepublish step

* 2.34.1-ovm

* reset iSynths (#946)

* Prepublish step

* 2.34.2

* Adding Shaula entry on releases

* Prepublish step

* 2.35.0-ovm

* Disable coverage in ci until its fixed (#950)

* SIP 100 Resolver & cache improvements (#951)

* Adding a new command to deploy an ovm instance pair for testing

* Minor lint fix

* Progress detecting unsafe deployments

* More robust OVM safety checks

* First OVM local deploy

* Working

* Return the right messenger addresses

* Predict deploy addresses in L2 deploys

* Tidier output in connect-bridge

* Remove log

* Add new logic and fix tests

* Use alt key

* Refactoring L2 prod tests

* Update interfaces

* Deposits working in L2 tests

* Progress with L2 withdrawal tests

* Linter fixes

* Withdrawals working in L2 prod tests

* Refactor depositAndMigrateEscrow() and add unit tests

* Add extra safety checks

* Use new addressResolver

* Deploy RewardEscrowV2 on local and local-ovm

* Connect-bridge command: Check if resolver needs imports and if bridge needs sync separately (#944)

* Prevent withdrawals on a suspended L2 system (#949)

* Prevent withdrawals on a suspended L2 system

* Also mocking SystemStatus on MintableSynthetix tests

Co-authored-by: justin j. moses <justin@synthetix.io>

* Adds a command that deploys an OVM pair of instances on local chains (#954)

* Adding a new command to deploy an ovm instance pair for testing

* Minor lint fix

* Progress detecting unsafe deployments

* More robust OVM safety checks

* First OVM local deploy

* Working

* Predict deploy addresses in L2 deploys

* Tidier output in connect-bridge

* Remove log

* Renamed some L2 functions (#961)

* New command: migrate-bridge (#925)

* Linter fixes

* Migrate bridge cmd uses getVersions

* Get latest bridge version directly from deployments

* Update to develop

* Added SystemSettings.crossDomainMessageGasLimit (#962)

* Added a system setting

* Minor fixes

* Added FlexibleStorage in L2 bridge unit tests

* Updates deploy-ovm-pair cmd to latest optimism-integration (#964)

* WIP: add initial deployment and tests

* Update interface

* Build ci

* Comment out tests

* Comment out test file

Co-authored-by: justin j. moses <justinjmoses@gmail.com>
Co-authored-by: Alejandro Santander <Palebluedot@gmail.com>
Co-authored-by: Jackson <jackosmacko@gmail.com>
Co-authored-by: Synthetix Team <team@synthetix.io>
Co-authored-by: Anton Jurisevic <zyzek@users.noreply.github.com>
Co-authored-by: Clinton Ennis <clinton@synthetix.io>
Co-authored-by: justin j. moses <justin@synthetix.io>
  • Loading branch information
8 people committed Dec 12, 2020
1 parent 004b35c commit aa4b14d
Show file tree
Hide file tree
Showing 27 changed files with 660 additions and 165 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Expand Up @@ -215,7 +215,7 @@ jobs:
- checkout
- attach_workspace:
at: .
- run: npm run test:multi-same-chain
- run: npm run test:prod:ovm
job-unit-tests-coverage:
working_directory: ~/repo
docker:
Expand Down
2 changes: 1 addition & 1 deletion .circleci/src/jobs/job-test-ovm-bridge.yml
Expand Up @@ -4,4 +4,4 @@ steps:
- checkout
- attach_workspace:
at: .
- run: npm run test:multi-same-chain
- run: npm run test:prod:ovm
2 changes: 1 addition & 1 deletion contracts/MintableSynthetix.sol
Expand Up @@ -59,7 +59,7 @@ contract MintableSynthetix is BaseSynthetix {
_rewardsDistribution.distributeRewards(amount);
}

function burnSecondary(address account, uint amount) external onlyBridge {
function burnSecondary(address account, uint amount) external onlyBridge systemActive {
tokenState.setBalanceOf(account, tokenState.balanceOf(account).sub(amount));
emitTransfer(account, address(0), amount);
totalSupply = totalSupply.sub(amount);
Expand Down
5 changes: 5 additions & 0 deletions contracts/MixinSystemSettings.sol
Expand Up @@ -24,6 +24,7 @@ contract MixinSystemSettings is MixinResolver {
bytes32 internal constant SETTING_AGGREGATOR_WARNING_FLAGS = "aggregatorWarningFlags";
bytes32 internal constant SETTING_TRADING_REWARDS_ENABLED = "tradingRewardsEnabled";
bytes32 internal constant SETTING_DEBT_SNAPSHOT_STALE_TIME = "debtSnapshotStaleTime";
bytes32 internal constant SETTING_CROSS_DOMAIN_MESSAGE_GAS_LIMIT = "crossDomainMessageGasLimit";

bytes32 internal constant CONTRACT_FLEXIBLESTORAGE = "FlexibleStorage";

Expand All @@ -38,6 +39,10 @@ contract MixinSystemSettings is MixinResolver {
return IFlexibleStorage(requireAndGetAddress(CONTRACT_FLEXIBLESTORAGE));
}

function getCrossDomainMessageGasLimit() internal view returns (uint) {
return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_CROSS_DOMAIN_MESSAGE_GAS_LIMIT);
}

function getTradingRewardsEnabled() internal view returns (bool) {
return flexibleStorage().getBoolValue(SETTING_CONTRACT_NAME, SETTING_TRADING_REWARDS_ENABLED);
}
Expand Down
20 changes: 11 additions & 9 deletions contracts/SynthetixBridgeToBase.sol
Expand Up @@ -4,6 +4,7 @@ pragma experimental ABIEncoderV2;
// Inheritance
import "./Owned.sol";
import "./MixinResolver.sol";
import "./MixinSystemSettings.sol";
import "./interfaces/ISynthetixBridgeToBase.sol";

// Internal references
Expand All @@ -15,9 +16,7 @@ import "./interfaces/IIssuer.sol";
import "@eth-optimism/contracts/build/contracts/iOVM/bridge/iOVM_BaseCrossDomainMessenger.sol";


contract SynthetixBridgeToBase is Owned, MixinResolver, ISynthetixBridgeToBase {
uint32 private constant CROSS_DOMAIN_MESSAGE_GAS_LIMIT = 3e6; //TODO: make this updateable

contract SynthetixBridgeToBase is Owned, MixinSystemSettings, ISynthetixBridgeToBase {
/* ========== ADDRESS RESOLVER CONFIGURATION ========== */
bytes32 private constant CONTRACT_EXT_MESSENGER = "ext:Messenger";
bytes32 private constant CONTRACT_SYNTHETIX = "Synthetix";
Expand All @@ -27,7 +26,7 @@ contract SynthetixBridgeToBase is Owned, MixinResolver, ISynthetixBridgeToBase {

// ========== CONSTRUCTOR ==========

constructor(address _owner, address _resolver) public Owned(_owner) MixinResolver(_resolver) {}
constructor(address _owner, address _resolver) public Owned(_owner) MixinSystemSettings(_resolver) {}

//
// ========== INTERNALS ============
Expand Down Expand Up @@ -66,28 +65,31 @@ contract SynthetixBridgeToBase is Owned, MixinResolver, ISynthetixBridgeToBase {

// ========== VIEWS ==========

function resolverAddressesRequired() public view returns (bytes32[] memory addresses) {
addresses = new bytes32[](5);
function resolverAddressesRequired() public view returns (bytes32[] memory) {
bytes32[] memory existingAddresses = MixinSystemSettings.resolverAddressesRequired();
bytes32[] memory addresses = new bytes32[](5);
addresses[0] = CONTRACT_EXT_MESSENGER;
addresses[1] = CONTRACT_SYNTHETIX;
addresses[2] = CONTRACT_BASE_SYNTHETIXBRIDGETOOPTIMISM;
addresses[3] = CONTRACT_ISSUER;
addresses[4] = CONTRACT_REWARDESCROW;
return combineArrays(existingAddresses, addresses);
}

// ========== PUBLIC FUNCTIONS =========

// invoked by user on L2
function initiateWithdrawal(uint amount) external {
require(issuer().debtBalanceOf(msg.sender, "sUSD") == 0, "Cannot withdraw with debt");

// instruct L2 Synthetix to burn this supply
synthetix().burnSecondary(msg.sender, amount);

// create message payload for L1
bytes memory messageData = abi.encodeWithSignature("completeWithdrawal(address,uint256)", msg.sender, amount);

// relay the message to Bridge on L1 via L2 Messenger
messenger().sendMessage(synthetixBridgeToOptimism(), messageData, CROSS_DOMAIN_MESSAGE_GAS_LIMIT);
messenger().sendMessage(synthetixBridgeToOptimism(), messageData, uint32(getCrossDomainMessageGasLimit()));

emit WithdrawalInitiated(msg.sender, amount);
}
Expand All @@ -104,7 +106,7 @@ contract SynthetixBridgeToBase is Owned, MixinResolver, ISynthetixBridgeToBase {
}

// invoked by Messenger on L2
function mintSecondaryFromDeposit(
function completeDeposit(
address account,
uint256 depositAmount,
uint256 escrowedAmount
Expand All @@ -120,7 +122,7 @@ contract SynthetixBridgeToBase is Owned, MixinResolver, ISynthetixBridgeToBase {
}

// invoked by Messenger on L2
function mintSecondaryFromDepositForRewards(uint256 amount) external onlyOptimismBridge {
function completeRewardDeposit(uint256 amount) external onlyOptimismBridge {
// now tell Synthetix to mint these tokens, deposited in L1, into reward escrow on L2
synthetix().mintSecondaryRewards(amount);

Expand Down
40 changes: 21 additions & 19 deletions contracts/SynthetixBridgeToOptimism.sol
Expand Up @@ -4,6 +4,7 @@ pragma experimental ABIEncoderV2;
// Inheritance
import "./Owned.sol";
import "./MixinResolver.sol";
import "./MixinSystemSettings.sol";
import "./interfaces/ISynthetixBridgeToOptimism.sol";

// Internal references
Expand All @@ -16,9 +17,7 @@ import "./interfaces/IRewardEscrowV2.sol";
import "@eth-optimism/contracts/build/contracts/iOVM/bridge/iOVM_BaseCrossDomainMessenger.sol";


contract SynthetixBridgeToOptimism is Owned, MixinResolver, ISynthetixBridgeToOptimism {
uint32 private constant CROSS_DOMAIN_MESSAGE_GAS_LIMIT = 3e6; //TODO: from constant to an updateable value

contract SynthetixBridgeToOptimism is Owned, MixinSystemSettings, ISynthetixBridgeToOptimism {
/* ========== ADDRESS RESOLVER CONFIGURATION ========== */
bytes32 private constant CONTRACT_EXT_MESSENGER = "ext:Messenger";
bytes32 private constant CONTRACT_SYNTHETIX = "Synthetix";
Expand All @@ -31,7 +30,7 @@ contract SynthetixBridgeToOptimism is Owned, MixinResolver, ISynthetixBridgeToOp

// ========== CONSTRUCTOR ==========

constructor(address _owner, address _resolver) public Owned(_owner) MixinResolver(_resolver) {
constructor(address _owner, address _resolver) public Owned(_owner) MixinSystemSettings(_resolver) {
activated = true;
}

Expand Down Expand Up @@ -72,14 +71,16 @@ contract SynthetixBridgeToOptimism is Owned, MixinResolver, ISynthetixBridgeToOp

/* ========== VIEWS ========== */

function resolverAddressesRequired() public view returns (bytes32[] memory addresses) {
addresses = new bytes32[](6);
function resolverAddressesRequired() public view returns (bytes32[] memory) {
bytes32[] memory existingAddresses = MixinSystemSettings.resolverAddressesRequired();
bytes32[] memory addresses = new bytes32[](6);
addresses[0] = CONTRACT_EXT_MESSENGER;
addresses[1] = CONTRACT_SYNTHETIX;
addresses[2] = CONTRACT_ISSUER;
addresses[3] = CONTRACT_REWARDSDISTRIBUTION;
addresses[4] = CONTRACT_OVM_SYNTHETIXBRIDGETOBASE;
addresses[5] = CONTRACT_REWARDESCROW;
return combineArrays(existingAddresses, addresses);
}

// ========== MODIFIERS ============
Expand All @@ -91,10 +92,10 @@ contract SynthetixBridgeToOptimism is Owned, MixinResolver, ISynthetixBridgeToOp

// ========== PUBLIC FUNCTIONS =========

function deposit(uint256 depositAmount) external requireActive {
function initiateDeposit(uint256 depositAmount) external requireActive {
require(issuer().debtBalanceOf(msg.sender, "sUSD") == 0, "Cannot deposit with debt");
// escrow amount should beset to 0
_deposit(depositAmount, 0);
_initiateDeposit(depositAmount, 0);
}

function depositAndMigrateEscrow(uint256 depositAmount, uint256[] calldata entryIDs) external requireActive {
Expand All @@ -117,20 +118,21 @@ contract SynthetixBridgeToOptimism is Owned, MixinResolver, ISynthetixBridgeToOp
vestingEntries
);
// relay the message to this contract on L2 via L1 Messenger
messenger().sendMessage(synthetixBridgeToBase(), messageData, CROSS_DOMAIN_MESSAGE_GAS_LIMIT);
messenger().sendMessage(synthetixBridgeToBase(), messageData, uint32(getCrossDomainMessageGasLimit()));
emit ExportedVestingEntries(msg.sender, escrowedAccountBalance, vestingEntries);
}
}
if (depositAmount > 0) {
_deposit(depositAmount, escrowedAccountBalance);
_initiateDeposit(depositAmount, escrowedAccountBalance);
}
}

// invoked by a generous user on L1
function rewardDeposit(uint256 amount) external requireActive {
function initiateRewardDeposit(uint amount) external requireActive {
// move the SNX into this contract
synthetixERC20().transferFrom(msg.sender, address(this), amount);
_rewardDeposit(amount);

_initiateRewardDeposit(amount);
}

// ========= RESTRICTED FUNCTIONS ==============
Expand Down Expand Up @@ -166,34 +168,34 @@ contract SynthetixBridgeToOptimism is Owned, MixinResolver, ISynthetixBridgeToOp
require(msg.sender == address(rewardsDistribution()), "Caller is not RewardsDistribution contract");

// to be here means I've been given an amount of SNX to distribute onto L2
_rewardDeposit(amount);
_initiateRewardDeposit(amount);
}

// ========== PRIVATE/INTERNAL FUNCTIONS =========

function _rewardDeposit(uint256 _amount) internal {
function _initiateRewardDeposit(uint256 _amount) internal {
// create message payload for L2
bytes memory messageData = abi.encodeWithSignature("mintSecondaryFromDepositForRewards(uint256)", _amount);
bytes memory messageData = abi.encodeWithSignature("completeRewardDeposit(uint256)", _amount);

// relay the message to this contract on L2 via L1 Messenger
messenger().sendMessage(synthetixBridgeToBase(), messageData, CROSS_DOMAIN_MESSAGE_GAS_LIMIT);
messenger().sendMessage(synthetixBridgeToBase(), messageData, uint32(getCrossDomainMessageGasLimit()));

emit RewardDeposit(msg.sender, _amount);
}

function _deposit(uint256 _depositAmount, uint256 _escrowAmount) private {
function _initiateDeposit(uint256 _depositAmount, uint256 _escrowAmount) private {
// Transfer SNX to L2
// First, move the SNX into this contract
synthetixERC20().transferFrom(msg.sender, address(this), _depositAmount);
// create message payload for L2
bytes memory messageData = abi.encodeWithSignature(
"mintSecondaryFromDeposit(address,uint256,uint256)",
"completeDeposit(address,uint256,uint256)",
msg.sender,
_depositAmount,
_escrowAmount
);
// relay the message to this contract on L2 via L1 Messenger
messenger().sendMessage(synthetixBridgeToBase(), messageData, CROSS_DOMAIN_MESSAGE_GAS_LIMIT);
messenger().sendMessage(synthetixBridgeToBase(), messageData, uint32(getCrossDomainMessageGasLimit()));
emit Deposit(msg.sender, _depositAmount, _escrowAmount);
}

Expand Down
14 changes: 14 additions & 0 deletions contracts/SystemSettings.sol
Expand Up @@ -122,8 +122,21 @@ contract SystemSettings is Owned, MixinSystemSettings, ISystemSettings {
return getTradingRewardsEnabled();
}

function crossDomainMessageGasLimit() external view returns (uint) {
return getCrossDomainMessageGasLimit();
}

// ========== RESTRICTED ==========

function setCrossDomainMessageGasLimit(uint _crossDomainMessageGasLimit) external onlyOwner {
flexibleStorage().setUIntValue(
SETTING_CONTRACT_NAME,
SETTING_CROSS_DOMAIN_MESSAGE_GAS_LIMIT,
_crossDomainMessageGasLimit
);
emit CrossDomainMessageGasLimitChanged(_crossDomainMessageGasLimit);
}

function setTradingRewardsEnabled(bool _tradingRewardsEnabled) external onlyOwner {
flexibleStorage().setBoolValue(SETTING_CONTRACT_NAME, SETTING_TRADING_REWARDS_ENABLED, _tradingRewardsEnabled);
emit TradingRewardsEnabled(_tradingRewardsEnabled);
Expand Down Expand Up @@ -243,6 +256,7 @@ contract SystemSettings is Owned, MixinSystemSettings, ISystemSettings {
}

// ========== EVENTS ==========
event CrossDomainMessageGasLimitChanged(uint newLimit);
event TradingRewardsEnabled(bool enabled);
event WaitingPeriodSecsUpdated(uint waitingPeriodSecs);
event PriceDeviationThresholdUpdated(uint threshold);
Expand Down
8 changes: 4 additions & 4 deletions contracts/interfaces/ISynthetixBridgeToBase.sol
Expand Up @@ -9,14 +9,14 @@ interface ISynthetixBridgeToBase {
function initiateWithdrawal(uint amount) external;

// invoked by the xDomain messenger on L2
function mintSecondaryFromDeposit(
function completeDeposit(
address account,
uint amount,
uint escrowAmount
uint depositAmount,
uint escrowedAmount
) external;

// invoked by the xDomain messenger on L2
function mintSecondaryFromDepositForRewards(uint amount) external;
function completeRewardDeposit(uint amount) external;

// invoked by the xDomain messenger on L2
function importVestingEntries(
Expand Down
2 changes: 1 addition & 1 deletion contracts/interfaces/ISynthetixBridgeToOptimism.sol
Expand Up @@ -6,7 +6,7 @@ interface ISynthetixBridgeToOptimism {
function completeWithdrawal(address account, uint amount) external;

// invoked by users on L1
function deposit(uint amount) external;
function initiateDeposit(uint amount) external;

// invoked users on L1
function depositAndMigrateEscrow(uint256 depositAmount, uint256[] calldata entryIDs) external;
Expand Down
1 change: 1 addition & 0 deletions index.js
Expand Up @@ -81,6 +81,7 @@ const defaults = {
kovan: '0x6292aa9a6650ae14fbf974e5029f36f95a1848fd',
},
INITIAL_ISSUANCE: w3utils.toWei(`${100e6}`),
CROSS_DOMAIN_MESSAGE_GAS_LIMIT: `${3e6}`,
};

/**
Expand Down
28 changes: 14 additions & 14 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Expand Up @@ -24,6 +24,7 @@
"test:ovm": "buidler test --ovm --optimizer",
"test:prod": "buidler test:prod --network localhost --optimizer",
"test:prod:ovm": "concurrently --kill-others --success first \"wait-port 8545 && wait-port 9545 && mocha test/optimism --timeout 900000\"",
"test:prod:ovm:escrow": "concurrently --kill-others --success first \"wait-port 8545 && wait-port 9545 && mocha test/optimism-escrow --timeout 900000\"",
"test:prod:gas": "buidler test:prod --gas --network localhost --optimizer --gas-output-file test-gas-used-prod.log",
"test:deployments": "mocha test/deployments -- --timeout 15000",
"test:etherscan": "node test/etherscan",
Expand Down
1 change: 1 addition & 0 deletions publish/index.js
Expand Up @@ -25,6 +25,7 @@ require('./src/commands/fork').cmd(program);
require('./src/commands/prepare-deploy').cmd(program);
require('./src/commands/prepare-deploy-detect-diff').cmd(program);
require('./src/commands/connect-bridge').cmd(program);
require('./src/commands/migrate-bridge').cmd(program);
require('./src/commands/deploy-ovm-pair').cmd(program);

program.parse(process.argv);

0 comments on commit aa4b14d

Please sign in to comment.