Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
plugin
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
JIRA
JIRA
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
link33
plugin
Commits
c1da9d02
Commit
c1da9d02
authored
Sep 30, 2021
by
hezhengjun
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add draft sol code for bridgevmxgo
parent
c81872d0
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
1739 additions
and
0 deletions
+1739
-0
BridgeBank.sol
plugin/dapp/bridgevmxgo/contracts/BridgeBank/BridgeBank.sol
+337
-0
BridgeToken.sol
plugin/dapp/bridgevmxgo/contracts/BridgeBank/BridgeToken.sol
+27
-0
EvmAssetBank.sol
...in/dapp/bridgevmxgo/contracts/BridgeBank/EvmAssetBank.sol
+273
-0
GoAssetBank.sol
plugin/dapp/bridgevmxgo/contracts/BridgeBank/GoAssetBank.sol
+0
-0
BridgeRegistry.sol
plugin/dapp/bridgevmxgo/contracts/BridgeRegistry.sol
+40
-0
GoAssetBridge.sol
plugin/dapp/bridgevmxgo/contracts/GoAssetBridge.sol
+368
-0
Oracle.sol
plugin/dapp/bridgevmxgo/contracts/Oracle.sol
+278
-0
Valset.sol
plugin/dapp/bridgevmxgo/contracts/Valset.sol
+416
-0
No files found.
plugin/dapp/bridgevmxgo/contracts/BridgeBank/BridgeBank.sol
0 → 100644
View file @
c1da9d02
pragma solidity ^0.5.0;
import "./GoAssetBank.sol";
import "./EvmAssetBank.sol";
import "../Oracle.sol";
import "../GoAssetBridge.sol";
/**
* @title BridgeBank
* @dev Bank contract which coordinates asset-related functionality.
* GoAssetBank manages the minting and burning of tokens which
* represent go contract issued assets, while EvmAssetBank manages
* the locking and unlocking of Chain33 and ERC20 token assets
* based on Chain33.
**/
contract BridgeBank is GoAssetBank, EvmAssetBank {
using SafeMath for uint256;
address public operator;
Oracle public oracle;
GoAssetBridge public goAssetBridge;
/*
* @dev: Constructor, sets operator
*/
constructor (
address _operatorAddress,
address _oracleAddress,
address _goAssetBridgeAddress
)
public
{
operator = _operatorAddress;
oracle = Oracle(_oracleAddress);
goAssetBridge = GoAssetBridge(_goAssetBridgeAddress);
}
/*
* @dev: Modifier to restrict access to operator
*/
modifier onlyOperator() {
require(
msg.sender == operator,
'Must be BridgeBank operator.'
);
_;
}
/*
* @dev: Modifier to restrict access to Offline
*/
modifier onlyOffline() {
require(
msg.sender == offlineSave,
'Must be onlyOffline.'
);
_;
}
/*
* @dev: Modifier to restrict access to the oracle
*/
modifier onlyOracle()
{
require(
msg.sender == address(oracle),
"Access restricted to the oracle"
);
_;
}
/*
* @dev: Modifier to restrict access to the goAsset bridge
*/
modifier onlyGoAssetBridge()
{
require(
msg.sender == address(goAssetBridge),
"Access restricted to the goAsset bridge"
);
_;
}
/*
* @dev: Fallback function allows operator to send funds to the bank directly
* This feature is used for testing and is available at the operator's own risk.
*/
function() external payable onlyOffline {}
/*
* @dev: Creates a new BridgeToken
*
* @param _symbol: The new BridgeToken's symbol
* @return: The new BridgeToken contract's address
*/
function createNewBridgeToken(
string memory _symbol
)
public
onlyOperator
returns(address)
{
return deployNewBridgeToken(_symbol);
}
/*
* @dev: Mints new BankTokens
*
* @param _goAssetSender: The goAsset sender's address.
* @param _chain33Recipient: The intended recipient's Chain33 address.
* @param _bridgeTokenAddress: The bridge token address
* @param _symbol: goAsset token symbol
* @param _amount: number of goAsset tokens to be minted
*/
function mintBridgeTokens(
address _goAssetSender,
address payable _intendedRecipient,
address _bridgeTokenAddress,
string memory _symbol,
uint256 _amount
)
public
onlyGoAssetBridge
{
return mintNewBridgeTokens(
_goAssetSender,
_intendedRecipient,
_bridgeTokenAddress,
_symbol,
_amount
);
}
/*
* @dev: Burns bank tokens
*
* @param _goAssetReceiver: The _goAsset receiver address in bytes.
* @param _goAssetTokenAddress: The currency type
* @param _amount: number of goAsset tokens to be burned
*/
function burnBridgeTokens(
address _goAssetReceiver,
address _goAssetTokenAddress,
uint256 _amount
)
public
{
return burnGoAssetTokens(
msg.sender,
_goAssetReceiver,
_goAssetTokenAddress,
_amount
);
}
/*
* @dev: addToken2LockList used to add token with the specified address to be
* allowed locked from GoAsset
*
* @param _token: token contract address
* @param _symbol: token symbol
*/
function addToken2LockList(
address _token,
string memory _symbol
)
public
onlyOperator
{
addToken2AllowLock(_token, _symbol);
}
/*
* @dev: configTokenOfflineSave used to config threshold to trigger tranfer token to offline account
* when the balance of locked token reaches
*
* @param _token: token contract address
* @param _symbol:token symbol,just used for double check that token address and symbol is consistent
* @param _threshold: _threshold to trigger transfer
* @param _percents: amount to transfer per percents of threshold
*/
function configLockedTokenOfflineSave(
address _token,
string memory _symbol,
uint256 _threshold,
uint8 _percents
)
public
onlyOperator
{
if (address(0) != _token) {
require(keccak256(bytes(BridgeToken(_token).symbol())) == keccak256(bytes(_symbol)), "token address and symbol is not consistent");
} else {
require(keccak256(bytes("BTY")) == keccak256(bytes(_symbol)), "token address and symbol is not consistent");
}
configOfflineSave4Lock(_token, _symbol, _threshold, _percents);
}
/*
* @dev: configOfflineSaveAccount used to config offline account to receive token
* when the balance of locked token reaches threshold
*
* @param _offlineSave: receiver address
*/
function configOfflineSaveAccount(address payable _offlineSave) public onlyOperator
{
offlineSave = _offlineSave;
}
/*
* @dev: Locks received Chain33 funds.
*
* @param _recipient: bytes representation of destination address.
* @param _token: token address in origin chain (0x0 if chain33)
* @param _amount: value of deposit
*/
function lock(
bytes memory _recipient,
address _token,
uint256 _amount
)
public
availableNonce()
payable
{
string memory symbol;
// Chain33 deposit
if (msg.value > 0) {
require(
_token == address(0),
"BTY deposits require the 'token' address to be the null address"
);
require(
msg.value == _amount,
"The transactions value must be equal the specified amount(BTY decimal is 8)"
);
// Set the the symbol to BTY
symbol = "BTY";
// ERC20 deposit
} else {
require(
BridgeToken(_token).transferFrom(msg.sender, address(this), _amount),
"Contract token allowances insufficient to complete this lock request"
);
// Set symbol to the ERC20 token's symbol
symbol = BridgeToken(_token).symbol();
require(
tokenAllow2Lock[keccak256(abi.encodePacked(symbol))] == _token,
'The token is not allowed to be locked from Chain33.'
);
}
lockFunds(
msg.sender,
_recipient,
_token,
symbol,
_amount
);
}
/*
* @dev: Unlocks Chain33 and ERC20 tokens held on the contract.
*
* @param _recipient: recipient's Chain33 address
* @param _token: token contract address
* @param _symbol: token symbol
* @param _amount: wei amount or ERC20 token count
\ */
function unlock(
address payable _recipient,
address _token,
string memory _symbol,
uint256 _amount
)
public
onlyGoAssetBridge
hasLockedFunds(
_token,
_amount
)
canDeliver(
_token,
_amount
)
{
unlockFunds(
_recipient,
_token,
_symbol,
_amount
);
}
/*
* @dev: Exposes an item's current status.
*
* @param _id: The item in question.
* @return: Boolean indicating the lock status.
*/
function getGoAssetDepositStatus(
bytes32 _id
)
public
view
returns(bool)
{
return isLockedGoAssetDeposit(_id);
}
/*
* @dev: Allows access to a GoAsset deposit's information via its unique identifier.
*
* @param _id: The deposit to be viewed.
* @return: Original sender's Chain33 address.
* @return: Intended GoAsset recipient's address in bytes.
* @return: The lock deposit's currency, denoted by a token address.
* @return: The amount locked in the deposit.
* @return: The deposit's unique nonce.
*/
function viewGoAssetDeposit(
bytes32 _id
)
public
view
returns(bytes memory, address payable, address, uint256)
{
return getGoAssetDeposit(_id);
}
}
\ No newline at end of file
plugin/dapp/bridgevmxgo/contracts/BridgeBank/BridgeToken.sol
0 → 100644
View file @
c1da9d02
pragma solidity ^0.5.0;
import "../../openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol";
import "../../openzeppelin-solidity/contracts/token/ERC20/ERC20Burnable.sol";
import "../../openzeppelin-solidity/contracts/token/ERC20/ERC20Detailed.sol";
/**
* @title BridgeToken
* @dev Mintable, ERC20 compatible BankToken for use by BridgeBank
**/
contract BridgeToken is ERC20Mintable, ERC20Burnable, ERC20Detailed {
constructor(
string memory _symbol
)
public
ERC20Detailed(
_symbol,
_symbol,
8
)
{
// Intentionally left blank
}
}
\ No newline at end of file
plugin/dapp/bridgevmxgo/contracts/BridgeBank/EvmAssetBank.sol
0 → 100644
View file @
c1da9d02
pragma solidity ^0.5.0;
import "../../openzeppelin-solidity/contracts/math/SafeMath.sol";
import "./BridgeToken.sol";
/*
* @title: EvmAssetBank
* @dev: EvmAsset bank which locks Chain33/ERC20 token deposits, and unlocks
* Chain33/ERC20 tokens once the prophecy has been successfully processed.
* @dev:当emv资产转移到go合约时,用于锁定资产;
* 当emv资产从go合约进行提币时,用于解锁资产;
*/
contract EvmAssetBank {
using SafeMath for uint256;
address payable public offlineSave;
uint256 public lockNonce;
mapping(address => uint256) public lockedFunds;
mapping(bytes32 => address) public tokenAllow2Lock;
mapping(address => OfflineSaveCfg) public offlineSaveCfgs;
uint8 public lowThreshold = 5;
uint8 public highThreshold = 80;
struct OfflineSaveCfg {
address token;
string symbol;
uint256 _threshold;
uint8 _percents;
}
/*
* @dev: Event declarations
*/
event LogLock(
address _from,
bytes _to,
address _token,
string _symbol,
uint256 _value,
uint256 _nonce
);
event LogUnlock(
address _to,
address _token,
string _symbol,
uint256 _value
);
/*
* @dev: Modifier declarations
*/
modifier hasLockedFunds(
address _token,
uint256 _amount
) {
require(
lockedFunds[_token] >= _amount,
"The Bank does not hold enough locked tokens to fulfill this request."
);
_;
}
modifier canDeliver(
address _token,
uint256 _amount
)
{
if(_token == address(0)) {
require(
address(this).balance >= _amount,
'Insufficient Chain33 balance for delivery.'
);
} else {
require(
BridgeToken(_token).balanceOf(address(this)) >= _amount,
'Insufficient ERC20 token balance for delivery.'
);
}
_;
}
modifier availableNonce() {
require(
lockNonce + 1 > lockNonce,
'No available nonces.'
);
_;
}
/*
* @dev: Constructor which sets the lock nonce
*/
constructor()
public
{
lockNonce = 0;
}
/*
* @dev: addToken2AllowLock used to add token with the specified address to be
* allowed locked from GoAsset
*
* @param _token: token contract address
* @param _symbol: token symbol
*/
function addToken2AllowLock(
address _token,
string memory _symbol
)
internal
{
bytes32 symHash = keccak256(abi.encodePacked(_symbol));
address tokenQuery = tokenAllow2Lock[symHash];
require(tokenQuery == address(0), 'The token with the same symbol has been added to lock allow list already.');
tokenAllow2Lock[symHash] = _token;
}
/*
* @dev: addToken2AllowLock used to add token with the specified address to be
* allowed locked from GoAsset
*
* @param _symbol: token symbol
*/
function getLockedTokenAddress(string memory _symbol) public view returns(address)
{
bytes32 symHash = keccak256(abi.encodePacked(_symbol));
return tokenAllow2Lock[symHash];
}
/*
* @dev: configOfflineSave4Lock used to config threshold to trigger tranfer token to offline account
* when the balance of locked token reaches
*
* @param _token: token contract address
* @param _symbol:token symbol,just used for double check that token address and symbol is consistent
* @param _threshold: _threshold to trigger transfer
* @param _percents: amount to transfer per percents of threshold
*/
function configOfflineSave4Lock(
address _token,
string memory _symbol,
uint256 _threshold,
uint8 _percents
)
internal
{
require(
_percents >= lowThreshold && _percents <= highThreshold,
"The percents to trigger should within range [5, 80]"
);
OfflineSaveCfg memory offlineSaveCfg = OfflineSaveCfg(
_token,
_symbol,
_threshold,
_percents
);
offlineSaveCfgs[_token] = offlineSaveCfg;
}
/*
* @dev: getofflineSaveCfg used to get token's offline save configuration
*
* @param _token: token contract address
*/
function getofflineSaveCfg(address _token) public view returns(uint256, uint8)
{
OfflineSaveCfg memory offlineSaveCfg = offlineSaveCfgs[_token];
return (offlineSaveCfg._threshold, offlineSaveCfg._percents);
}
/*
* @dev: Creates a new Chain33 deposit with a unique id.
*
* @param _sender: The sender's Chain33 address.
* @param _recipient: The intended recipient's Chain33 address.
* @param _token: The currency type, either erc20 or Chain33.
* @param _amount: The amount of erc20 tokens/ Chain33 (in wei) to be itemized.
*/
function lockFunds(
address payable _sender,
bytes memory _recipient,
address _token,
string memory _symbol,
uint256 _amount
)
internal
{
// Incerment the lock nonce
lockNonce = lockNonce.add(1);
// Increment locked funds by the amount of tokens to be locked
lockedFunds[_token] = lockedFunds[_token].add(_amount);
emit LogLock(
_sender,
_recipient,
_token,
_symbol,
_amount,
lockNonce
);
if (address(0) == offlineSave) {
return;
}
uint256 balance;
if (address(0) == _token) {
balance = address(this).balance;
} else {
balance = BridgeToken(_token).balanceOf(address(this));
}
OfflineSaveCfg memory offlineSaveCfg = offlineSaveCfgs[_token];
//check not zero,so configured already
if (offlineSaveCfg._percents < lowThreshold) {
return;
}
if (balance < offlineSaveCfg._threshold ) {
return;
}
uint256 amount = offlineSaveCfg._percents * balance / 100;
if (address(0) == _token) {
offlineSave.transfer(amount);
} else {
require(BridgeToken(_token).transfer(offlineSave, amount), "Erc20 Token Transfer to offline Save account failed");
}
}
/*
* @dev: Unlocks funds held on contract and sends them to the
* intended recipient
*
* @param _recipient: recipient's Chain33 address
* @param _token: token contract address
* @param _symbol: token symbol
* @param _amount: wei amount or ERC20 token count
*/
function unlockFunds(
address payable _recipient,
address _token,
string memory _symbol,
uint256 _amount
)
internal
{
// Decrement locked funds mapping by the amount of tokens to be unlocked
lockedFunds[_token] = lockedFunds[_token].sub(_amount);
// Transfer funds to intended recipient
if (_token == address(0)) {
_recipient.transfer(_amount);
} else {
require(
BridgeToken(_token).transfer(_recipient, _amount),
"Token transfer failed"
);
}
emit LogUnlock(
_recipient,
_token,
_symbol,
_amount
);
}
}
plugin/dapp/bridgevmxgo/contracts/BridgeBank/GoAssetBank.sol
0 → 100644
View file @
c1da9d02
This diff is collapsed.
Click to expand it.
plugin/dapp/bridgevmxgo/contracts/BridgeRegistry.sol
0 → 100644
View file @
c1da9d02
pragma solidity ^0.5.0;
contract BridgeRegistry {
address public goAssetBridge;
address public bridgeBank;
address public oracle;
address public valset;
uint256 public deployHeight;
event LogContractsRegistered(
address _goAssetBridge,
address _bridgeBank,
address _oracle,
address _valset
);
constructor(
address _goAssetBridge,
address _bridgeBank,
address _oracle,
address _valset
)
public
{
goAssetBridge = _goAssetBridge;
bridgeBank = _bridgeBank;
oracle = _oracle;
valset = _valset;
deployHeight = block.number;
emit LogContractsRegistered(
goAssetBridge,
bridgeBank,
oracle,
valset
);
}
}
\ No newline at end of file
plugin/dapp/bridgevmxgo/contracts/GoAssetBridge.sol
0 → 100644
View file @
c1da9d02
pragma solidity ^0.5.0;
import "../openzeppelin-solidity/contracts/math/SafeMath.sol";
import "./Valset.sol";
import "./BridgeBank/BridgeBank.sol";
contract GoAssetBridge {
using SafeMath for uint256;
/*
* @dev: Public variable declarations
*/
address public operator;
Valset public valset;
address public oracle;
bool public hasOracle;
BridgeBank public bridgeBank;
bool public hasBridgeBank;
uint256 public prophecyClaimCount;
mapping(bytes32 => ProphecyClaim) public prophecyClaims;
enum Status {
Null,
Pending,
Success,
Failed
}
enum ClaimType {
Unsupported,
Burn,
Lock
}
struct ProphecyClaim {
ClaimType claimType;
address goAssetSender;
address payable chain33Receiver;
address originalValidator;
address tokenAddress;
string symbol;
uint256 amount;
Status status;
}
/*
* @dev: Event declarations
*/
event LogOracleSet(
address _oracle
);
event LogBridgeBankSet(
address _bridgeBank
);
event LogNewProphecyClaim(
uint256 _prophecyID,
ClaimType _claimType,
address _goAssetSender,
address payable _chain33Receiver,
address _validatorAddress,
address _tokenAddress,
string _symbol,
uint256 _amount
);
event LogProphecyCompleted(
bytes32 _claimID,
ClaimType _claimType
);
/*
* @dev: Modifier which only allows access to currently pending prophecies
*/
modifier isPending(
bytes32 _claimID
)
{
require(
isProphecyClaimActive(_claimID),
"Prophecy claim is not active"
);
_;
}
/*
* @dev: Modifier to restrict access to the operator.
*/
modifier onlyOperator()
{
require(
msg.sender == operator,
'Must be the operator.'
);
_;
}
/*
* @dev: Modifier to restrict access to the oracle.
*/
modifier onlyOracle()
{
require(
msg.sender == oracle,
'Must be the oracle.'
);
_;
}
/*
* @dev: The bridge is not active until oracle and bridge bank are set
*/
modifier isActive()
{
require(
hasOracle == true && hasBridgeBank == true,
"The Operator must set the oracle and bridge bank for bridge activation"
);
_;
}
/*
* @dev: Modifier to make sure the claim type is valid
*/
modifier validClaimType(
ClaimType _claimType
)
{
require(
_claimType == ClaimType.Burn || _claimType == ClaimType.Lock,
"The claim type must be ClaimType.Burn or ClaimType.Lock"
);
_;
}
/*
* @dev: Constructor
*/
constructor(
address _operator,
address _valset
)
public
{
prophecyClaimCount = 0;
operator = _operator;
valset = Valset(_valset);
hasOracle = false;
hasBridgeBank = false;
}
/*
* @dev: setOracle
*/
function setOracle(
address _oracle
)
public
onlyOperator
{
require(
!hasOracle,
"The Oracle cannot be updated once it has been set"
);
hasOracle = true;
oracle = _oracle;
emit LogOracleSet(
oracle
);
}
/*
* @dev: setBridgeBank
*/
function setBridgeBank(
address payable _bridgeBank
)
public
onlyOperator
{
require(
!hasBridgeBank,
"The Bridge Bank cannot be updated once it has been set"
);
hasBridgeBank = true;
bridgeBank = BridgeBank(_bridgeBank);
emit LogBridgeBankSet(
address(bridgeBank)
);
}
/*
* @dev: setNewProphecyClaim
* Sets a new burn or lock prophecy claim, adding it to the prophecyClaims mapping.
* Lock claims can only be created for BridgeTokens on BridgeBank's whitelist. The operator
* is responsible for adding them, and lock claims will fail until the operator has done so.
*/
function setNewProphecyClaim(
bytes32 _claimID,
uint8 _claimType,
address _goAssetSender,
address payable _chain33Receiver,
address _originalValidator,
address _tokenAddress,
string memory _symbol,
uint256 _amount
)
public
isActive
onlyOracle
{
// Increment the prophecy claim count
prophecyClaimCount = prophecyClaimCount.add(1);
ClaimType claimType = ClaimType(_claimType);
//overwrite the token address in case of lock
if (claimType == ClaimType.Lock) {
_tokenAddress = bridgeBank.getToken2address(_symbol);
}
// Create the new ProphecyClaim
ProphecyClaim memory prophecyClaim = ProphecyClaim(
claimType,
_goAssetSender,
_chain33Receiver,
_originalValidator,
_tokenAddress,
_symbol,
_amount,
Status.Pending
);
// Add the new ProphecyClaim to the mapping
prophecyClaims[_claimID] = prophecyClaim;
emit LogNewProphecyClaim(
prophecyClaimCount,
claimType,
_goAssetSender,
_chain33Receiver,
_originalValidator,
_tokenAddress,
_symbol,
_amount
);
}
/*
* @dev: completeClaim
* Allows for the completion of ProphecyClaims once processed by the Oracle.
* Burn claims unlock tokens stored by BridgeBank.
* Lock claims mint BridgeTokens on BridgeBank's token whitelist.
*/
function completeClaim(
bytes32 _claimID
)
public
isPending(_claimID)
{
require(
msg.sender == oracle,
"Only the Oracle may complete prophecies"
);
prophecyClaims[_claimID].status = Status.Success;
ClaimType claimType = prophecyClaims[_claimID].claimType;
if(claimType == ClaimType.Burn) {
unlockTokens(_claimID);
} else {
issueBridgeTokens(_claimID);
}
emit LogProphecyCompleted(
_claimID,
claimType
);
}
/*
* @dev: issueBridgeTokens
* Issues a request for the BridgeBank to mint new BridgeTokens
*/
function issueBridgeTokens(
bytes32 _claimID
)
internal
{
ProphecyClaim memory prophecyClaim = prophecyClaims[_claimID];
bridgeBank.mintBridgeTokens(
prophecyClaim.goAssetSender,
prophecyClaim.chain33Receiver,
prophecyClaim.tokenAddress,
prophecyClaim.symbol,
prophecyClaim.amount
);
}
/*
* @dev: unlockTokens
* Issues a request for the BridgeBank to unlock funds held on contract
*/
function unlockTokens(
bytes32 _claimID
)
internal
{
ProphecyClaim memory prophecyClaim = prophecyClaims[_claimID];
bridgeBank.unlock(
prophecyClaim.chain33Receiver,
prophecyClaim.tokenAddress,
prophecyClaim.symbol,
prophecyClaim.amount
);
}
/*
* @dev: isProphecyClaimActive
* Returns boolean indicating if the ProphecyClaim is active
*/
function isProphecyClaimActive(
bytes32 _claimID
)
public
view
returns(bool)
{
return prophecyClaims[_claimID].status == Status.Pending;
}
/*
* @dev: isProphecyValidatorActive
* Returns boolean indicating if the validator that originally
* submitted the ProphecyClaim is still an active validator
*/
function isProphecyClaimValidatorActive(
bytes32 _claimID
)
public
view
returns(bool)
{
return valset.isActiveValidator(
prophecyClaims[_claimID].originalValidator
);
}
/*
* @dev: Modifier to make sure the claim type is valid
*/
function isValidClaimType(uint8 _claimType) public pure returns(bool)
{
ClaimType claimType = ClaimType(_claimType);
if (claimType == ClaimType.Burn || claimType == ClaimType.Lock) {
return true;
}
return false;
}
}
plugin/dapp/bridgevmxgo/contracts/Oracle.sol
0 → 100644
View file @
c1da9d02
pragma solidity ^0.5.0;
import "../openzeppelin-solidity/contracts/math/SafeMath.sol";
import "./Valset.sol";
import "./GoAssetBridge.sol";
contract Oracle {
using SafeMath for uint256;
/*
* @dev: Public variable declarations
*/
GoAssetBridge public GoAssetBridge;
Valset public valset;
address public operator;
// Tracks the number of OracleClaims made on an individual BridgeClaim
mapping(bytes32 => address[]) public oracleClaimValidators;
mapping(bytes32 => mapping(address => bool)) public hasMadeClaim;
enum ClaimType {
Unsupported,
Burn,
Lock
}
/*
* @dev: Event declarations
*/
event LogNewOracleClaim(
bytes32 _claimID,
address _validatorAddress,
bytes _signature
);
event LogProphecyProcessed(
bytes32 _claimID,
uint256 _weightedSignedPower,
uint256 _weightedTotalPower,
address _submitter
);
/*
* @dev: Modifier to restrict access to the operator.
*/
modifier onlyOperator()
{
require(
msg.sender == operator,
'Must be the operator.'
);
_;
}
/*
* @dev: Modifier to restrict access to current ValSet validators
*/
modifier onlyValidator()
{
require(
valset.isActiveValidator(msg.sender),
"Must be an active validator"
);
_;
}
/*
* @dev: Modifier to restrict access to current ValSet validators
*/
modifier isPending(
bytes32 _claimID
)
{
require(
goAssetBridge.isProphecyClaimActive(
_claimID
) == true,
"The prophecy must be pending for this operation"
);
_;
}
/*
* @dev: Modifier to restrict the claim type must be burn or lock
*/
modifier isValidClaimType(
ClaimType _claimType
)
{
require(
goAssetBridge.isValidClaimType(
uint8(_claimType)
) == true,
"The claim type must be burn or lock"
);
_;
}
/*
* @dev: Constructor
*/
constructor(
address _operator,
address _valset,
address _goAssetBridge
)
public
{
operator = _operator;
goAssetBridge = GoAssetBridge(_goAssetBridge);
valset = Valset(_valset);
}
/*
* @dev: newOracleClaim
* Allows validators to make new OracleClaims on goAsset lock/burn prophecy,
* if the required vote power reached,just make it processed
* @param _claimType: burn or lock,
* @param _goAssetSender: goAsset sender,
* @param _chain33Receiver: receiver on chain33
* @param _tokenAddress: token address
* @param _symbol: token symbol
* @param _amount: amount
* @param _claimID: claim id
* @param _message: message for verifying
* @param _signature: need to recover sender
*/
function newOracleClaim(
ClaimType _claimType,
address _goAssetSender,
address payable _chain33Receiver,
address _tokenAddress,
string memory _symbol,
uint256 _amount,
bytes32 _claimID,
bytes memory _signature
)
public
onlyValidator
isValidClaimType(_claimType)
{
address validatorAddress = msg.sender;
// Validate the msg.sender's signature
require(
validatorAddress == valset.recover(
_claimID,
_signature
),
"Invalid _claimID signature."
);
// Confirm that this address has not already made an oracle claim on this _ClaimID
require(
!hasMadeClaim[_claimID][validatorAddress],
"Cannot make duplicate oracle claims from the same address."
);
if (oracleClaimValidators[_claimID].length == 0) {
goAssetBridge.setNewProphecyClaim(
_claimID,
uint8(_claimType),
_goAssetSender,
_chain33Receiver,
validatorAddress,
_tokenAddress,
_symbol,
_amount);
}
hasMadeClaim[_claimID][validatorAddress] = true;
oracleClaimValidators[_claimID].push(validatorAddress);
emit LogNewOracleClaim(
_claimID,
validatorAddress,
_signature
);
(bool valid, uint256 weightedSignedPower, uint256 weightedTotalPower ) = getClaimThreshold(_claimID);
if (true == valid) {
//if processed already,just emit an event
if (goAssetBridge.isProphecyClaimActive(_claimID) == true) {
completeClaim(_claimID);
}
emit LogProphecyProcessed(
_claimID,
weightedSignedPower,
weightedTotalPower,
msg.sender
);
}
}
/*
* @dev: checkBridgeProphecy
* Operator accessor method which checks if a prophecy has passed
* the validity threshold, without actually completing the prophecy.
*/
function checkBridgeProphecy(
bytes32 _claimID
)
public
view
onlyOperator
isPending(_claimID)
returns(bool, uint256, uint256)
{
require(
goAssetBridge.isProphecyClaimActive(
_claimID
) == true,
"Can only check active prophecies"
);
return getClaimThreshold(
_claimID
);
}
/*
* @dev: getClaimThreshold
* Calculates the status of a claim. The claim is considered valid if the
* combined active signatory validator powers pass the validation threshold.
* The hardcoded threshold is (Combined signed power * 2) >= (Total power * 3).
*/
function getClaimThreshold(
bytes32 _claimID
)
internal
view
returns(bool, uint256, uint256)
{
uint256 signedPower = 0;
uint256 totalPower = valset.totalPower();
// Iterate over the signatory addresses
for (uint256 i = 0; i < oracleClaimValidators[_claimID].length; i = i.add(1)) {
address signer = oracleClaimValidators[_claimID][i];
// Only add the power of active validators
if(valset.isActiveValidator(signer)) {
signedPower = signedPower.add(
valset.getValidatorPower(
signer
)
);
}
}
// Calculate if weighted signed power has reached threshold of weighted total power
uint256 weightedSignedPower = signedPower.mul(3);
uint256 weightedTotalPower = totalPower.mul(2);
bool hasReachedThreshold = weightedSignedPower >= weightedTotalPower;
return(
hasReachedThreshold,
weightedSignedPower,
weightedTotalPower
);
}
/*
* @dev: completeClaim
* Completes a claim by completing the corresponding BridgeClaim
* on the GoAssetBridge.
*/
function completeClaim(
bytes32 _claimID
)
internal
{
goAssetBridge.completeClaim(
_claimID
);
}
}
\ No newline at end of file
plugin/dapp/bridgevmxgo/contracts/Valset.sol
0 → 100644
View file @
c1da9d02
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment