Skip to content

Commit

Permalink
Merge pull request #114 from vzotova/confirmation
Browse files Browse the repository at this point in the history
Operator confirmation from Coordinator to TACo application
  • Loading branch information
cygnusv authored Sep 8, 2023
2 parents 95de44f + b2efc21 commit 3456fdc
Show file tree
Hide file tree
Showing 28 changed files with 989 additions and 448 deletions.
3 changes: 2 additions & 1 deletion .solhint.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"state-visibility": "error",
"no-global-import": "off",
"func-named-parameters": "off",
"prettier/prettier": "error"
"prettier/prettier": "error",
"no-complex-fallback": "warn"
}
}
69 changes: 43 additions & 26 deletions ape-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ dependencies:
- name: openzeppelin
github: OpenZeppelin/openzeppelin-contracts
version: 4.9.1
config_override:
solidity:
version: 0.8.20
evm_version: paris
- name: openzeppelin-upgradeable
github: OpenZeppelin/openzeppelin-contracts-upgradeable
version: 4.9.1
Expand All @@ -35,34 +39,38 @@ deployments:
polygon:
mainnet:
- contract_type: DAI
address: '0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063'
address: "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063"
- contract_type: fx_child
address: "0x8397259c983751DAf40400790063935a11afa28a"
mumbai:
- contract_type: DAI
address: '0x001B3B4d0F3714Ca98ba10F6042DaEbF0B1B7b6F'
address: "0x001B3B4d0F3714Ca98ba10F6042DaEbF0B1B7b6F"
- contract_type: StakeInfo
address: '0xC1379866Fb0c100DCBFAb7b470009C4827D47DD8'
- fx_child: '0xCf73231F28B7331BBe3124B907840A94851f9f11'
- verify: False
address: "0xC1379866Fb0c100DCBFAb7b470009C4827D47DD8"
- contract_type: fx_child
address: "0xCf73231F28B7331BBe3124B907840A94851f9f11"
- contract_type: TACoChildApplication
address: "0x68E95C2548363Bf5856667065Bc1B89CC498969F"
ethereum:
local:
- nu_token_supply: 1_000_000_000
pre_min_authorization: 40000000000000000000000
pre_min_operator_seconds: 86400 # one day in seconds
pre_min_operator_seconds: 86400 # one day in seconds
pre_hash_algorithm: 1
pre_base_penalty: 2
pre_penalty_history_coefficient: 0
pre_percentage_penalty_coefficient: 100000
reward_duration: 604800 # one week in seconds
deauthorization_duration: 5184000 # 60 days in seconds
reward_duration: 604800 # one week in seconds
deauthorization_duration: 5184000 # 60 days in seconds
verify: False
rinkeby:
- nu_token: '0x78D591D90a4a768B9D2790deA465D472b6Fe0f18'
- nu_token: "0x78D591D90a4a768B9D2790deA465D472b6Fe0f18"
nu_token_supply: 1_000_000_000
t_staking: '0x18eFb520dA5D387982C860a64855C14C0AcADF3F'
work_lock: '0x0000000000000000000000000000000000000000'
staking_escrow: '0x6A6F917a3FF3d33d26BB4743140F205486cD6B4B'
t_staking: "0x18eFb520dA5D387982C860a64855C14C0AcADF3F"
work_lock: "0x0000000000000000000000000000000000000000"
staking_escrow: "0x6A6F917a3FF3d33d26BB4743140F205486cD6B4B"
pre_min_authorization: 40000000000000000000000
pre_min_operator_seconds: 86400 # one day in seconds
pre_min_operator_seconds: 86400 # one day in seconds
verify: True
# TODO: is there a batter way to manage multiple deployments on the same network?
# goerli-tapir:
Expand All @@ -76,29 +84,38 @@ deployments:
# pre_min_authorization: 40000000000000000000000
# pre_min_operator_seconds: 86400 # one day in seconds
goerli: # -lynx
- t_staking: '0x81eEefb7B1b3313C89976910096F8f1487301Bb1'
- t_staking: "0x81eEefb7B1b3313C89976910096F8f1487301Bb1"
pre_min_authorization: 40000000000000000000000
pre_min_operator_seconds: 86400 # one day in seconds
pre_min_operator_seconds: 86400 # one day in seconds
ritual_timeout: 3600
max_dkg_size: 8
pre_application: '0x685b8Fd02aB87d8FfFff7346cB101A5cE4185bf3'
pre_application: "0x685b8Fd02aB87d8FfFff7346cB101A5cE4185bf3"
verify: True
reward_duration: 604800 # one week in seconds
deauthorization_duration: 5184000 # 60 days in seconds
- contract_type: fx_root
address: "0x3d1d3E34f7fB6D26245E6640E1c50710eFFf15bA"
- contract_type: checkpoint_manager
address: "0x2890bA17EfE978480615e330ecB65333b880928e"
mumbai:
- stake_info_contract: '0xC1379866Fb0c100DCBFAb7b470009C4827D47DD8'
- stake_info_contract: "0xC1379866Fb0c100DCBFAb7b470009C4827D47DD8"
max_dkg_size: 16
ritual_timeout: 86400 # one day in seconds
ritual_timeout: 86400 # one day in seconds
verify: True
checkpoint_manager: '0x2890bA17EfE978480615e330ecB65333b880928e'
fx_root: '0x3d1d3E34f7fB6D26245E6640E1c50710eFFf15bA'
checkpoint_manager: "0x2890bA17EfE978480615e330ecB65333b880928e"
fx_root: "0x3d1d3E34f7fB6D26245E6640E1c50710eFFf15bA"
mainnet:
- nu_token: '0x4fE83213D56308330EC302a8BD641f1d0113A4Cc'
t_staking: '0x01B67b1194C75264d06F808A921228a95C765dd7'
work_lock: '0xe9778E69a961e64d3cdBB34CF6778281d34667c2'
staking_escrow: '0xbbD3C0C794F40c4f993B03F65343aCC6fcfCb2e2'
- nu_token: "0x4fE83213D56308330EC302a8BD641f1d0113A4Cc"
t_staking: "0x01B67b1194C75264d06F808A921228a95C765dd7"
work_lock: "0xe9778E69a961e64d3cdBB34CF6778281d34667c2"
staking_escrow: "0xbbD3C0C794F40c4f993B03F65343aCC6fcfCb2e2"
pre_min_authorization: 40000000000000000000000
pre_min_operator_seconds: 86400 # one day in seconds
pre_min_operator_seconds: 86400 # one day in seconds
verify: True

- contract_type: fx_root
address: "0xfe5e5D361b2ad62c541bAb87C45a0B9B018389a2"
- contract_type: checkpoint_manager
address: "0x86e4dc95c7fbdbf52e33d563bbdb00823894c287"

test:
mnemonic: test test test test test test test test test test test junk
Expand Down
71 changes: 34 additions & 37 deletions contracts/contracts/TACoApplication.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol";
import "@threshold/contracts/staking/IApplication.sol";
import "@threshold/contracts/staking/IStaking.sol";
import "./coordination/IUpdatableStakeInfo.sol";
import "./coordination/ITACoRootToChild.sol";
import "./coordination/ITACoChildToRoot.sol";

/**
* @title TACo Application
* @notice Contract distributes rewards for participating in app and slashes for violating rules
*/
contract TACoApplication is IApplication, OwnableUpgradeable {
contract TACoApplication is IApplication, ITACoChildToRoot, OwnableUpgradeable {
using SafeERC20 for IERC20;
using SafeCast for uint256;

Expand Down Expand Up @@ -127,13 +128,6 @@ contract TACoApplication is IApplication, OwnableUpgradeable {
uint256 startTimestamp
);

/**
* @notice Signals that an operator address is confirmed
* @param stakingProvider Staking provider address
* @param operator Operator address
*/
event OperatorConfirmed(address indexed stakingProvider, address indexed operator);

struct StakingProviderInfo {
address operator;
bool operatorConfirmed;
Expand All @@ -153,7 +147,7 @@ contract TACoApplication is IApplication, OwnableUpgradeable {
IStaking public immutable tStaking;
IERC20 public immutable token;

IUpdatableStakeInfo public updatableStakeInfo;
ITACoRootToChild public childApplication;
address public adjudicator;

mapping(address => StakingProviderInfo) public stakingProviderInfo;
Expand Down Expand Up @@ -237,16 +231,12 @@ contract TACoApplication is IApplication, OwnableUpgradeable {
/**
* @notice Set contract for multi-chain interactions
*/
function setUpdatableStakeInfo(IUpdatableStakeInfo _updatableStakeInfo) external onlyOwner {
function setChildApplication(ITACoRootToChild _childApplication) external onlyOwner {
require(
address(_updatableStakeInfo) != address(updatableStakeInfo),
address(_childApplication) != address(childApplication),
"New address must not be equal to the current one"
);
if (address(_updatableStakeInfo) != address(0)) {
// trying to call contract to be sure that is correct address
_updatableStakeInfo.updateOperator(address(0), address(0));
}
updatableStakeInfo = _updatableStakeInfo;
childApplication = _childApplication;
}

/**
Expand Down Expand Up @@ -681,27 +671,34 @@ contract TACoApplication is IApplication, OwnableUpgradeable {
info.operator = _operator;
info.operatorStartTimestamp = uint64(block.timestamp);
emit OperatorBonded(_stakingProvider, _operator, previousOperator, block.timestamp);
_releaseOperator(_stakingProvider);

info.operatorConfirmed = false;
if (address(childApplication) != address(0)) {
childApplication.updateOperator(_stakingProvider, _operator);
}
}

/**
* @notice Make a confirmation by operator
*/
function confirmOperatorAddress() external {
address stakingProvider = _stakingProviderFromOperator[msg.sender];
require(isAuthorized(stakingProvider), "No stake associated with the operator");
StakingProviderInfo storage info = stakingProviderInfo[stakingProvider];
require(!info.operatorConfirmed, "Operator address is already confirmed");
// solhint-disable-next-line avoid-tx-origin
require(msg.sender == tx.origin, "Only operator with real address can make a confirmation");

updateRewardInternal(stakingProvider);
info.operatorConfirmed = true;
authorizedOverall += info.authorized;
emit OperatorConfirmed(stakingProvider, msg.sender);
function confirmOperatorAddress(address _operator) external override {
require(
msg.sender == address(childApplication),
"Only child application allowed to confirm operator"
);
address stakingProvider = _stakingProviderFromOperator[_operator];
// TODO only in case of desync, maybe just exit?
// require(stakingProvider != address(0), "Operator has no bond with staking provider");
if (stakingProvider == address(0)) {
return;
}

if (address(updatableStakeInfo) != address(0)) {
updatableStakeInfo.updateOperator(stakingProvider, msg.sender);
StakingProviderInfo storage info = stakingProviderInfo[stakingProvider];
if (!info.operatorConfirmed) {
updateRewardInternal(stakingProvider);
info.operatorConfirmed = true;
authorizedOverall += info.authorized;
emit OperatorConfirmed(stakingProvider, _operator);
}
}

Expand All @@ -712,8 +709,8 @@ contract TACoApplication is IApplication, OwnableUpgradeable {
*/
function _releaseOperator(address _stakingProvider) internal {
stakingProviderInfo[_stakingProvider].operatorConfirmed = false;
if (address(updatableStakeInfo) != address(0)) {
updatableStakeInfo.updateOperator(_stakingProvider, address(0));
if (address(childApplication) != address(0)) {
childApplication.updateOperator(_stakingProvider, address(0));
}
}

Expand All @@ -724,10 +721,10 @@ contract TACoApplication is IApplication, OwnableUpgradeable {
address _stakingProvider,
StakingProviderInfo storage _info
) internal {
if (address(updatableStakeInfo) != address(0)) {
// TODO send both authorized and eligible amounts in case of slashing from StakeInfo
if (address(childApplication) != address(0)) {
// TODO send both authorized and eligible amounts in case of slashing from child app
uint96 eligibleAmount = getEligibleAmount(_info);
updatableStakeInfo.updateAmount(_stakingProvider, eligibleAmount);
childApplication.updateAuthorization(_stakingProvider, eligibleAmount);
}
}

Expand Down
20 changes: 12 additions & 8 deletions contracts/contracts/coordination/Coordinator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "./FlatRateFeeModel.sol";
import "./IReimbursementPool.sol";
import "../lib/BLS12381.sol";
import "../../threshold/IAccessControlApplication.sol";
import "../../threshold/ITACoChildApplication.sol";
import "./IEncryptionAuthorizer.sol";

/**
Expand Down Expand Up @@ -83,7 +83,7 @@ contract Coordinator is AccessControlDefaultAdminRules, FlatRateFeeModel {
bytes32 public constant INITIATOR_ROLE = keccak256("INITIATOR_ROLE");
bytes32 public constant TREASURY_ROLE = keccak256("TREASURY_ROLE");

IAccessControlApplication public immutable application;
ITACoChildApplication public immutable application;

Ritual[] public rituals;
uint32 public timeout;
Expand All @@ -97,14 +97,14 @@ contract Coordinator is AccessControlDefaultAdminRules, FlatRateFeeModel {
mapping(bytes32 => uint32) internal ritualPublicKeyRegistry;

constructor(
IAccessControlApplication _stakes,
ITACoChildApplication _application,
uint32 _timeout,
uint16 _maxDkgSize,
address _admin,
IERC20 _currency,
uint256 _feeRatePerSecond
) AccessControlDefaultAdminRules(0, _admin) FlatRateFeeModel(_currency, _feeRatePerSecond) {
application = _stakes;
application = _application;
timeout = _timeout;
maxDkgSize = _maxDkgSize;
}
Expand Down Expand Up @@ -147,14 +147,18 @@ contract Coordinator is AccessControlDefaultAdminRules, FlatRateFeeModel {
_setRoleAdmin(INITIATOR_ROLE, bytes32(0));
}

function setProviderPublicKey(BLS12381.G2Point calldata _publicKey) public {
function setProviderPublicKey(BLS12381.G2Point calldata _publicKey) external {
uint32 lastRitualId = uint32(rituals.length);
address provider = application.stakingProviderFromOperator(msg.sender);
address stakingProvider = application.stakingProviderFromOperator(msg.sender);
require(stakingProvider != address(0), "Operator has no bond with staking provider");

ParticipantKey memory newRecord = ParticipantKey(lastRitualId, _publicKey);
keysHistory[provider].push(newRecord);
keysHistory[stakingProvider].push(newRecord);

emit ParticipantPublicKeySet(lastRitualId, provider, _publicKey);
emit ParticipantPublicKeySet(lastRitualId, stakingProvider, _publicKey);
// solhint-disable-next-line avoid-tx-origin
require(msg.sender == tx.origin, "Only operator with real address can set public key");
application.confirmOperatorAddress(msg.sender);
}

function getProviderPublicKey(
Expand Down
18 changes: 18 additions & 0 deletions contracts/contracts/coordination/ITACoChildToRoot.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// SPDX-License-Identifier: AGPL-3.0-or-later

pragma solidity ^0.8.0;

/**
* @title ITACoChildToRoot
* @notice Interface for x-chain interactions from coordinator to application
*/
interface ITACoChildToRoot {
/**
* @notice Signals that an operator address is confirmed
* @param stakingProvider Staking provider address
* @param operator Operator address
*/
event OperatorConfirmed(address indexed stakingProvider, address indexed operator);

function confirmOperatorAddress(address operator) external;
}
16 changes: 16 additions & 0 deletions contracts/contracts/coordination/ITACoRootToChild.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: AGPL-3.0-or-later

pragma solidity ^0.8.0;

/**
* @title ITACoRootToChild
* @notice Interface for x-chain interactions from application to coordinator
*/
interface ITACoRootToChild {
event OperatorUpdated(address indexed stakingProvider, address indexed operator);
event AuthorizationUpdated(address indexed stakingProvider, uint96 amount);

function updateOperator(address stakingProvider, address operator) external;

function updateAuthorization(address stakingProvider, uint96 amount) external;
}
18 changes: 0 additions & 18 deletions contracts/contracts/coordination/IUpdatableStakeInfo.sol

This file was deleted.

Loading

0 comments on commit 3456fdc

Please sign in to comment.