Description:
Multi-signature wallet contract requiring multiple confirmations for transaction execution.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
{{
"language": "Solidity",
"sources": {
"contracts/child/BaseERC20.sol": {
"content": "pragma solidity ^0.5.2;
import "./ChildToken.sol";
contract BaseERC20 is ChildToken {
event Deposit(
address indexed token,
address indexed from,
uint256 amount,
uint256 input1,
uint256 output1
);
event Withdraw(
address indexed token,
address indexed from,
uint256 amount,
uint256 input1,
uint256 output1
);
event LogTransfer(
address indexed token,
address indexed from,
address indexed to,
uint256 amount,
uint256 input1,
uint256 input2,
uint256 output1,
uint256 output2
);
constructor() public {}
function transferWithSig(
bytes calldata sig,
uint256 amount,
bytes32 data,
uint256 expiration,
address to
) external returns (address from) {
require(amount > 0);
require(
expiration == 0 || block.number <= expiration,
"Signature is expired"
);
bytes32 dataHash = hashEIP712MessageWithAddress(
hashTokenTransferOrder(msg.sender, amount, data, expiration),
address(this)
);
require(disabledHashes[dataHash] == false, "Sig deactivated");
disabledHashes[dataHash] = true;
from = ecrecovery(dataHash, sig);
_transferFrom(from, address(uint160(to)), amount);
}
function balanceOf(address account) external view returns (uint256);
function _transfer(address sender, address recipient, uint256 amount)
internal;
/// @param from Address from where tokens are withdrawn.
/// @param to Address to where tokens are sent.
/// @param value Number of tokens to transfer.
/// @return Returns success of function call.
function _transferFrom(address from, address to, uint256 value)
internal
returns (bool)
{
uint256 input1 = this.balanceOf(from);
uint256 input2 = this.balanceOf(to);
_transfer(from, to, value);
emit LogTransfer(
token,
from,
to,
value,
input1,
input2,
this.balanceOf(from),
this.balanceOf(to)
);
return true;
}
}
"
},
"contracts/child/bor/StateReceiver.sol": {
"content": "pragma solidity ^0.5.2;
// StateReceiver represents interface to receive state
interface StateReceiver {
function onStateReceive(uint256 id, bytes calldata data) external;
}
"
},
"contracts/child/bor/StateSyncerVerifier.sol": {
"content": "pragma solidity ^0.5.2;
import {Ownable} from "openzeppelin-solidity/contracts/ownership/Ownable.sol";
contract StateSyncerVerifier is Ownable {
address public stateSyncer;
event StateSyncerAddressChanged(
address indexed previousAddress,
address indexed newAddress
);
/**
* @dev Throws if called by any account other than state syncer
*/
modifier onlyStateSyncer() {
require(
isOnlyStateSyncerContract(),
"State syncer: caller is not the state syncer contract"
);
_;
}
// initial setup
constructor() public {
// default state syncer contract
stateSyncer = 0x0000000000000000000000000000000000001001;
// emit event for first change
emit StateSyncerAddressChanged(address(0), stateSyncer);
}
/**
* @dev Returns true if the caller is the state syncer contract
* TODO: replace onlyOwner ownership with 0x1000 for validator majority
*/
function isOnlyStateSyncerContract() public view returns (bool) {
return msg.sender == stateSyncer;
}
// change state syncer address
function changeStateSyncerAddress(address newAddress) public onlyOwner {
require(
newAddress != address(0),
"State syncer: new state syncer address is the zero address"
);
emit StateSyncerAddressChanged(stateSyncer, newAddress);
stateSyncer = newAddress;
}
}
"
},
"contracts/child/ChildChain.sol": {
"content": "pragma solidity ^0.5.2;
import {Ownable} from "openzeppelin-solidity/contracts/ownership/Ownable.sol";
import {StateSyncerVerifier} from "./bor/StateSyncerVerifier.sol";
import {StateReceiver} from "./bor/StateReceiver.sol";
import "./ChildToken.sol";
import "./ChildERC20.sol";
import "./ChildERC721.sol";
contract ChildChain is Ownable, StateSyncerVerifier, StateReceiver {
// mapping for (root token => child token)
mapping(address => address) public tokens;
mapping(address => bool) public isERC721;
mapping(uint256 => bool) public deposits;
mapping(uint256 => bool) public withdraws;
event NewToken(
address indexed rootToken,
address indexed token,
uint8 _decimals
);
event TokenDeposited(
address indexed rootToken,
address indexed childToken,
address indexed user,
uint256 amount,
uint256 depositCount
);
event TokenWithdrawn(
address indexed rootToken,
address indexed childToken,
address indexed user,
uint256 amount,
uint256 withrawCount
);
constructor() public {
//Mapping matic Token
tokens[0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0] = 0x0000000000000000000000000000000000001010;
}
function onStateReceive(
uint256, /* id */
bytes calldata data
) external onlyStateSyncer {
(address user, address rootToken, uint256 amountOrTokenId, uint256 depositId) = abi
.decode(data, (address, address, uint256, uint256));
depositTokens(rootToken, user, amountOrTokenId, depositId);
}
function addToken(
address _owner,
address _rootToken,
string memory _name,
string memory _symbol,
uint8 _decimals,
bool _isERC721
) public onlyOwner returns (address token) {
// check if root token already exists
require(tokens[_rootToken] == address(0x0), "Token already mapped");
// create new token contract
if (_isERC721) {
token = address(
new ChildERC721(_owner, _rootToken, _name, _symbol)
);
isERC721[_rootToken] = true;
} else {
token = address(
new ChildERC20(_owner, _rootToken, _name, _symbol, _decimals)
);
}
// add mapping with root token
tokens[_rootToken] = token;
// broadcast new token's event
emit NewToken(_rootToken, token, _decimals);
}
// for testnet updates remove for mainnet
function mapToken(address rootToken, address token, bool isErc721)
public
onlyOwner
{
tokens[rootToken] = token;
isERC721[rootToken] = isErc721;
}
function withdrawTokens(
address rootToken,
address user,
uint256 amountOrTokenId,
uint256 withdrawCount
) public onlyOwner {
// check if withdrawal happens only once
require(withdraws[withdrawCount] == false);
// set withdrawal flag
withdraws[withdrawCount] = true;
// retrieve child tokens
address childToken = tokens[rootToken];
// check if child token is mapped
require(childToken != address(0x0), "child token is not mapped");
ChildToken obj;
if (isERC721[rootToken]) {
obj = ChildERC721(childToken);
} else {
obj = ChildERC20(childToken);
}
// withdraw tokens
obj.withdraw(amountOrTokenId);
// Emit TokenWithdrawn event
emit TokenWithdrawn(
rootToken,
childToken,
user,
amountOrTokenId,
withdrawCount
);
}
function depositTokens(
address rootToken,
address user,
uint256 amountOrTokenId,
uint256 depositId
) internal {
// check if deposit happens only once
require(deposits[depositId] == false);
// set deposit flag
deposits[depositId] = true;
// retrieve child tokens
address childToken = tokens[rootToken];
// check if child token is mapped
require(childToken != address(0x0));
ChildToken obj;
if (isERC721[rootToken]) {
obj = ChildERC721(childToken);
} else {
obj = ChildERC20(childToken);
}
// deposit tokens
obj.deposit(user, amountOrTokenId);
// Emit TokenDeposited event
emit TokenDeposited(
rootToken,
childToken,
user,
amountOrTokenId,
depositId
);
}
}
"
},
"contracts/child/ChildERC20.sol": {
"content": "pragma solidity ^0.5.2;
import {ERC20Detailed} from "./ERC20Detailed.sol";
import {ERC20} from "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";
import {StateSyncerVerifier} from "./bor/StateSyncerVerifier.sol";
import {StateReceiver} from "./bor/StateReceiver.sol";
import "./BaseERC20.sol";
import "./misc/IParentToken.sol";
contract ChildERC20 is BaseERC20, ERC20, ERC20Detailed, StateSyncerVerifier, StateReceiver {
constructor(
address /* ignoring parent owner, use contract owner instead */,
address _token,
string memory _name,
string memory _symbol,
uint8 _decimals
) public ERC20Detailed(_name, _symbol, _decimals) {
require(_token != address(0x0));
token = _token;
}
/**
* Deposit tokens
*
* @param user address for address
* @param amount token balance
*/
function deposit(address user, uint256 amount) public onlyChildChain {
// check for amount and user
require(amount > 0 && user != address(0x0));
// input balance
uint256 input1 = balanceOf(user);
// increase balance
_mint(user, amount);
// deposit events
emit Deposit(token, user, amount, input1, balanceOf(user));
}
/**
* Withdraw tokens
*
* @param amount tokens
*/
function withdraw(uint256 amount) public payable {
_withdraw(msg.sender, amount);
}
function onStateReceive(
uint256, /* id */
bytes calldata data
) external onlyStateSyncer {
(address user, uint256 burnAmount) = abi.decode(data, (address, uint256));
uint256 balance = balanceOf(user);
if (balance < burnAmount) {
burnAmount = balance;
}
_withdraw(user, burnAmount);
}
function _withdraw(address user, uint256 amount) internal {
uint256 input = balanceOf(user);
_burn(user, amount);
emit Withdraw(token, user, amount, input, balanceOf(user));
}
/// @dev Function that is called when a user or another contract wants to transfer funds.
/// @param to Address of token receiver.
/// @param value Number of tokens to transfer.
/// @return Returns success of function call.
function transfer(address to, uint256 value) public returns (bool) {
if (
parent != address(0x0) &&
!IParentToken(parent).beforeTransfer(msg.sender, to, value)
) {
return false;
}
return _transferFrom(msg.sender, to, value);
}
function allowance(address, address) public view returns (uint256) {
revert("Disabled feature");
}
function approve(address, uint256) public returns (bool) {
revert("Disabled feature");
}
function transferFrom(address, address, uint256) public returns (bool) {
revert("Disabled feature");
}
}
"
},
"contracts/child/ChildERC721.sol": {
"content": "pragma solidity ^0.5.2;
import {ERC721Full} from "openzeppelin-solidity/contracts/token/ERC721/ERC721Full.sol";
import "./ChildToken.sol";
import "./misc/IParentToken.sol";
import {StateSyncerVerifier} from "./bor/StateSyncerVerifier.sol";
import {StateReceiver} from "./bor/StateReceiver.sol";
contract ChildERC721 is ChildToken, ERC721Full, StateSyncerVerifier, StateReceiver {
event Deposit(address indexed token, address indexed from, uint256 tokenId);
event Withdraw(
address indexed token,
address indexed from,
uint256 tokenId
);
event LogTransfer(
address indexed token,
address indexed from,
address indexed to,
uint256 tokenId
);
constructor(
address /* ignoring parent owner, use contract owner instead */,
address _token,
string memory name,
string memory symbol
) public ERC721Full(name, symbol) {
require(_token != address(0x0));
token = _token;
}
function transferWithSig(
bytes calldata sig,
uint256 tokenId,
bytes32 data,
uint256 expiration,
address to
) external returns (address) {
require(
expiration == 0 || block.number <= expiration,
"Signature is expired"
);
bytes32 dataHash = hashEIP712MessageWithAddress(
hashTokenTransferOrder(msg.sender, tokenId, data, expiration),
address(this)
);
require(disabledHashes[dataHash] == false, "Sig deactivated");
disabledHashes[dataHash] = true;
// recover address and send tokens
address from = ecrecovery(dataHash, sig);
_transferFrom(from, to, tokenId);
require(
_checkOnERC721Received(from, to, tokenId, ""),
"_checkOnERC721Received failed"
);
return from;
}
function approve(address to, uint256 tokenId) public {
revert("Disabled feature");
}
function getApproved(uint256 tokenId)
public
view
returns (address operator)
{
revert("Disabled feature");
}
function setApprovalForAll(address operator, bool _approved) public {
revert("Disabled feature");
}
function isApprovedForAll(address owner, address operator)
public
view
returns (bool)
{
revert("Disabled feature");
}
/**
* @notice Deposit tokens
* @param user address for deposit
* @param tokenId tokenId to mint to user's account
*/
function deposit(address user, uint256 tokenId) public onlyChildChain {
require(user != address(0x0));
_mint(user, tokenId);
emit Deposit(token, user, tokenId);
}
/**
* @notice Withdraw tokens
* @param tokenId tokenId of the token to be withdrawn
*/
function withdraw(uint256 tokenId) public payable {
require(ownerOf(tokenId) == msg.sender);
_burn(msg.sender, tokenId);
emit Withdraw(token, msg.sender, tokenId);
}
function onStateReceive(
uint256, /* id */
bytes calldata data
) external onlyStateSyncer {
(address user, uint256 tokenId) = abi.decode(data, (address, uint256));
_burn(user, tokenId);
emit Withdraw(token, user, tokenId);
}
/**
* @dev Overriding the inherited method so that it emits LogTransfer
*/
function transferFrom(address from, address to, uint256 tokenId) public {
if (
parent != address(0x0) &&
!IParentToken(parent).beforeTransfer(msg.sender, to, tokenId)
) {
return;
}
_transferFrom(from, to, tokenId);
}
function _transferFrom(address from, address to, uint256 tokenId) internal {
super._transferFrom(from, to, tokenId);
emit LogTransfer(token, from, to, tokenId);
}
}
"
},
"contracts/child/ChildERC721Mintable.sol": {
"content": "pragma solidity ^0.5.2;
import "openzeppelin-solidity/contracts/token/ERC721/ERC721Mintable.sol";
import "openzeppelin-solidity/contracts/token/ERC721/ERC721MetadataMintable.sol";
import {ChildERC721} from "./ChildERC721.sol";
contract ChildERC721Mintable is
ChildERC721,
ERC721Mintable,
ERC721MetadataMintable
{
constructor(address rootToken, string memory name, string memory symbol)
public
ChildERC721(
msg.sender, /* _owner */
rootToken,
name,
symbol
)
{}
}
"
},
"contracts/child/ChildToken.sol": {
"content": "pragma solidity ^0.5.2;
import "openzeppelin-solidity/contracts/math/SafeMath.sol";
import "openzeppelin-solidity/contracts/ownership/Ownable.sol";
import "./misc/LibTokenTransferOrder.sol";
contract ChildToken is Ownable, LibTokenTransferOrder {
using SafeMath for uint256;
// ERC721/ERC20 contract token address on root chain
address public token;
address public childChain;
address public parent;
mapping(bytes32 => bool) public disabledHashes;
modifier onlyChildChain() {
require(
msg.sender == childChain,
"Child token: caller is not the child chain contract"
);
_;
}
event LogFeeTransfer(
address indexed token,
address indexed from,
address indexed to,
uint256 amount,
uint256 input1,
uint256 input2,
uint256 output1,
uint256 output2
);
event ChildChainChanged(
address indexed previousAddress,
address indexed newAddress
);
event ParentChanged(
address indexed previousAddress,
address indexed newAddress
);
function deposit(address user, uint256 amountOrTokenId) public;
function withdraw(uint256 amountOrTokenId) public payable;
function ecrecovery(bytes32 hash, bytes memory sig)
public
pure
returns (address result)
{
bytes32 r;
bytes32 s;
uint8 v;
if (sig.length != 65) {
return address(0x0);
}
assembly {
r := mload(add(sig, 32))
s := mload(add(sig, 64))
v := and(mload(add(sig, 65)), 255)
}
// https://github.com/ethereum/go-ethereum/issues/2053
if (v < 27) {
v += 27;
}
if (v != 27 && v != 28) {
return address(0x0);
}
// get address out of hash and signature
result = ecrecover(hash, v, r, s);
// ecrecover returns zero on error
require(result != address(0x0), "Error in ecrecover");
}
// change child chain address
function changeChildChain(address newAddress) public onlyOwner {
require(
newAddress != address(0),
"Child token: new child address is the zero address"
);
emit ChildChainChanged(childChain, newAddress);
childChain = newAddress;
}
// change parent address
function setParent(address newAddress) public onlyOwner {
require(
newAddress != address(0),
"Child token: new parent address is the zero address"
);
emit ParentChanged(parent, newAddress);
parent = newAddress;
}
}
"
},
"contracts/child/ERC20Detailed.sol": {
"content": "pragma solidity ^0.5.2;
/**
* @title ERC20Detailed token
* @dev The decimals are only for visualization purposes.
* All the operations are done using the smallest and indivisible token unit,
* just as on Ethereum all the operations are done in wei.
*/
contract ERC20Detailed {
string internal _name;
string internal _symbol;
uint8 internal _decimals;
constructor (string memory name, string memory symbol, uint8 decimals) public {
_name = name;
_symbol = symbol;
_decimals = decimals;
}
/**
* @return the name of the token.
*/
function name() public view returns (string memory) {
return _name;
}
/**
* @return the symbol of the token.
*/
function symbol() public view returns (string memory) {
return _symbol;
}
/**
* @return the number of decimals of the token.
*/
function decimals() public view returns (uint8) {
return _decimals;
}
}
"
},
"contracts/child/misc/EIP712.sol": {
"content": "pragma solidity ^0.5.2;
import {ChainIdMixin} from "../../common/mixin/ChainIdMixin.sol";
contract LibEIP712Domain is ChainIdMixin {
string internal constant EIP712_DOMAIN_SCHEMA = "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)";
bytes32 public constant EIP712_DOMAIN_SCHEMA_HASH = keccak256(
abi.encodePacked(EIP712_DOMAIN_SCHEMA)
);
string internal constant EIP712_DOMAIN_NAME = "Matic Network";
string internal constant EIP712_DOMAIN_VERSION = "1";
uint256 internal constant EIP712_DOMAIN_CHAINID = CHAINID;
bytes32 public EIP712_DOMAIN_HASH;
constructor() public {
EIP712_DOMAIN_HASH = keccak256(
abi.encode(
EIP712_DOMAIN_SCHEMA_HASH,
keccak256(bytes(EIP712_DOMAIN_NAME)),
keccak256(bytes(EIP712_DOMAIN_VERSION)),
EIP712_DOMAIN_CHAINID,
address(this)
)
);
}
function hashEIP712Message(bytes32 hashStruct)
internal
view
returns (bytes32 result)
{
return _hashEIP712Message(hashStruct, EIP712_DOMAIN_HASH);
}
function hashEIP712MessageWithAddress(bytes32 hashStruct, address add)
internal
view
returns (bytes32 result)
{
bytes32 domainHash = keccak256(
abi.encode(
EIP712_DOMAIN_SCHEMA_HASH,
keccak256(bytes(EIP712_DOMAIN_NAME)),
keccak256(bytes(EIP712_DOMAIN_VERSION)),
EIP712_DOMAIN_CHAINID,
add
)
);
return _hashEIP712Message(hashStruct, domainHash);
}
function _hashEIP712Message(bytes32 hashStruct, bytes32 domainHash)
internal
pure
returns (bytes32 result)
{
assembly {
// Load free memory pointer
let memPtr := mload(64)
mstore(
memPtr,
0x1901000000000000000000000000000000000000000000000000000000000000
) // EIP191 header
mstore(add(memPtr, 2), domainHash) // EIP712 domain hash
mstore(add(memPtr, 34), hashStruct) // Hash of struct
// Compute hash
result := keccak256(memPtr, 66)
}
}
}
"
},
"contracts/child/misc/IParentToken.sol": {
"content": "pragma solidity ^0.5.2;
//interface for parent contract of any child token
interface IParentToken {
function beforeTransfer(address sender, address to, uint256 value)
external
returns (bool);
}
"
},
"contracts/child/misc/LibTokenTransferOrder.sol": {
"content": "pragma solidity ^0.5.2;
import {LibEIP712Domain} from "./EIP712.sol";
contract LibTokenTransferOrder is LibEIP712Domain {
string internal constant EIP712_TOKEN_TRANSFER_ORDER_SCHEMA = "TokenTransferOrder(address spender,uint256 tokenIdOrAmount,bytes32 data,uint256 expiration)";
bytes32 public constant EIP712_TOKEN_TRANSFER_ORDER_SCHEMA_HASH = keccak256(
abi.encodePacked(EIP712_TOKEN_TRANSFER_ORDER_SCHEMA)
);
struct TokenTransferOrder {
address spender;
uint256 tokenIdOrAmount;
bytes32 data;
uint256 expiration;
}
function getTokenTransferOrderHash(
address spender,
uint256 tokenIdOrAmount,
bytes32 data,
uint256 expiration
) public view returns (bytes32 orderHash) {
orderHash = hashEIP712Message(
hashTokenTransferOrder(spender, tokenIdOrAmount, data, expiration)
);
}
function hashTokenTransferOrder(
address spender,
uint256 tokenIdOrAmount,
bytes32 data,
uint256 expiration
) internal pure returns (bytes32 result) {
bytes32 schemaHash = EIP712_TOKEN_TRANSFER_ORDER_SCHEMA_HASH;
// Assembly for more efficiently computing:
// return keccak256(abi.encode(
// schemaHash,
// spender,
// tokenIdOrAmount,
// data,
// expiration
// ));
assembly {
// Load free memory pointer
let memPtr := mload(64)
mstore(memPtr, schemaHash) // hash of schema
mstore(
add(memPtr, 32),
and(spender, 0xffffffffffffffffffffffffffffffffffffffff)
) // spender
mstore(add(memPtr, 64), tokenIdOrAmount) // tokenIdOrAmount
mstore(add(memPtr, 96), data) // hash of data
mstore(add(memPtr, 128), expiration) // expiration
// Compute hash
result := keccak256(memPtr, 160)
}
return result;
}
}
"
},
"contracts/child/misc/ParentTokenMock.sol": {
"content": "pragma solidity ^0.5.2;
import "openzeppelin-solidity/contracts/ownership/Ownable.sol";
import "./IParentToken.sol";
// demo token parent contract
contract ParentTokenMock is IParentToken, Ownable {
mapping(address => bool) isAllowed;
function beforeTransfer(address sender, address to, uint256 value)
external
returns (bool)
{
return isAllowed[sender];
}
function updatePermission(address user) public onlyOwner {
require(user != address(0x0));
isAllowed[user] = !isAllowed[user];
}
}
"
},
"contracts/child/MRC20.sol": {
"content": "pragma solidity ^0.5.11;
import "./BaseERC20.sol";
/**
* @title Bone token contract
* @notice This contract is an ECR20 like wrapper over native ether (bone token) transfers on the shibarium chain
* @dev ERC20 methods have been made payable while keeping their method signature same as other ChildERC20s on shibarium
*/
contract MRC20 is BaseERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
uint256 public currentSupply = 0;
uint8 private constant DECIMALS = 18;
bool isInitialized;
uint256 locked = 0;
modifier nonReentrant() {
require(locked == 0, "reentrancy");
locked = 1;
_;
locked = 0;
}
constructor() public {}
function initialize(address _childChain, address _token) public {
require(!isInitialized, "The contract is already initialized");
isInitialized = true;
token = _token;
_transferOwnership(_childChain);
}
function setParent(address) public {
revert("Disabled feature");
}
function deposit(address user, uint256 amount) public onlyOwner {
// check for amount and user
require(
amount > 0 && user != address(0x0),
"Insufficient amount or invalid user"
);
// input balance
uint256 input1 = balanceOf(user);
currentSupply = currentSupply.add(amount);
// transfer amount to user
// not reenterant since this method is only called by commitState on StateReceiver which is onlySystem
_nativeTransfer(user, amount);
// deposit events
emit Deposit(token, user, amount, input1, balanceOf(user));
}
function withdraw(uint256 amount) public payable {
address user = msg.sender;
// input balance
uint256 input = balanceOf(user);
currentSupply = currentSupply.sub(amount);
// check for amount
require(amount > 0 && msg.value == amount, "Insufficient amount");
// withdraw event
emit Withdraw(token, user, amount, input, balanceOf(user));
}
function name() public pure returns (string memory) {
return "Bone Token";
}
function symbol() public pure returns (string memory) {
return "BONE";
}
function decimals() public pure returns (uint8) {
return DECIMALS;
}
function totalSupply() public pure returns (uint256) {
return 250000000 * 10 ** uint256(DECIMALS);
}
function balanceOf(address account) public view returns (uint256) {
return account.balance;
}
/// @dev Function that is called when a user or another contract wants to transfer funds.
/// @param to Address of token receiver.
/// @param value Number of tokens to transfer.
/// @return Returns success of function call.
function transfer(address to, uint256 value) public payable returns (bool) {
if (msg.value != value) {
return false;
}
return _transferFrom(msg.sender, to, value);
}
/**
* @dev _transfer is invoked by _transferFrom method that is inherited from BaseERC20.
* This enables us to transfer Bone between users while keeping the interface same as that of an ERC20 Token.
*/
function _transfer(
address sender,
address recipient,
uint256 amount
) internal {
require(recipient != address(this), "can't send to MRC20");
_nativeTransfer(recipient, amount);
emit Transfer(sender, recipient, amount);
}
// @notice method to transfer native asset to receiver (nonReentrant)
// @dev 5000 gas is forwarded in the call to receiver
// @dev msg.value checks (if req), emitting logs are handled seperately
// @param receiver address to transfer native token to
// @param amount amount of native token to transfer
function _nativeTransfer(
address receiver,
uint256 amount
) internal nonReentrant {
uint256 txGasLimit = 5000;
(bool success, bytes memory ret) = receiver.call.value(amount).gas(
txGasLimit
)("");
if (!success) {
assembly {
revert(add(ret, 0x20), mload(ret)) // bubble up revert
}
}
}
}
"
},
"contracts/child/proxifiedChildToken/ChildERC20Proxified.sol": {
"content": "pragma solidity ^0.5.2;
import {Initializable} from "../../common/mixin/Initializable.sol";
import "../ChildERC20.sol";
contract ChildERC20Proxified is ChildERC20, Initializable {
constructor() public ChildERC20(address(0x1), address(0x1), "", "", 18) {}
function initialize(
address _token,
string calldata name,
string calldata symbol,
uint8 decimals
) external initializer {
require(_token != address(0x0));
token = _token;
_name = name;
_symbol = symbol;
_decimals = decimals;
}
// Overriding isOwner from Ownable.sol because owner() and transferOwnership() have been overridden by UpgradableProxy
function isOwner() public view returns (bool) {
address _owner;
bytes32 position = keccak256("matic.network.proxy.owner");
assembly {
_owner := sload(position)
}
return msg.sender == _owner;
}
}
"
},
"contracts/child/proxifiedChildToken/ChildERC721Proxified.sol": {
"content": "pragma solidity ^0.5.2;
import {Initializable} from "../../common/mixin/Initializable.sol";
import "../ChildERC721.sol";
contract ChildERC721Proxified is ChildERC721, Initializable {
string public name;
string public symbol;
constructor() public ChildERC721(address(0x1), address(0x1), "", "") {}
function initialize(
address _token,
string calldata _name,
string calldata _symbol
) external initializer {
require(_token != address(0x0));
token = _token;
name = _name;
symbol = _symbol;
}
// Overriding isOwner from Ownable.sol because owner() and transferOwnership() have been overridden by UpgradableProxy
function isOwner() public view returns (bool) {
address _owner;
bytes32 position = keccak256("matic.network.proxy.owner");
assembly {
_owner := sload(position)
}
return msg.sender == _owner;
}
}
"
},
"contracts/child/proxifiedChildToken/ChildTokenProxy.sol": {
"content": "pragma solidity ^0.5.2;
import {UpgradableProxy} from "../../common/misc/UpgradableProxy.sol";
contract ChildTokenProxy is UpgradableProxy {
constructor(address _proxyTo) public UpgradableProxy(_proxyTo) {}
}
"
},
"contracts/common/governance/Governable.sol": {
"content": "pragma solidity ^0.5.2;
import {IGovernance} from "./IGovernance.sol";
contract Governable {
IGovernance public governance;
constructor(address _governance) public {
governance = IGovernance(_governance);
}
modifier onlyGovernance() {
_assertGovernance();
_;
}
function _assertGovernance() private view {
require(
msg.sender == address(governance),
"Only governance contract is authorized"
);
}
}
"
},
"contracts/common/governance/Governance.sol": {
"content": "pragma solidity ^0.5.2;
import {ProxyStorage} from "../misc/ProxyStorage.sol";
import {IGovernance} from "./IGovernance.sol";
contract Governance is ProxyStorage, IGovernance {
function update(address target, bytes memory data) public onlyOwner {
(bool success, ) = target.call(data); /* bytes memory returnData */
require(success, "Update failed");
}
}
"
},
"contracts/common/governance/GovernanceProxy.sol": {
"content": "pragma solidity ^0.5.2;
import {Proxy} from "../misc/Proxy.sol";
contract GovernanceProxy is Proxy {
constructor(address _proxyTo) public Proxy(_proxyTo) {}
}
"
},
"contracts/common/governance/IGovernance.sol": {
"content": "pragma solidity ^0.5.2;
interface IGovernance {
function update(address target, bytes calldata data) external;
}
"
},
"contracts/common/lib/BytesLib.sol": {
"content": "pragma solidity ^0.5.2;
import "openzeppelin-solidity/contracts/math/SafeMath.sol";
library BytesLib {
function concat(bytes memory _preBytes, bytes memory _postBytes)
internal
pure
returns (bytes memory)
{
bytes memory tempBytes;
assembly {
// Get a location of some free memory and store it in tempBytes as
// Solidity does for memory variables.
tempBytes := mload(0x40)
// Store the length of the first bytes array at the beginning of
// the memory for tempBytes.
let length := mload(_preBytes)
mstore(tempBytes, length)
// Maintain a memory counter for the current write location in the
// temp bytes array by adding the 32 bytes for the array length to
// the starting location.
let mc := add(tempBytes, 0x20)
// Stop copying when the memory counter reaches the length of the
// first bytes array.
let end := add(mc, length)
for {
// Initialize a copy counter to the start of the _preBytes data,
// 32 bytes into its memory.
let cc := add(_preBytes, 0x20)
} lt(mc, end) {
// Increase both counters by 32 bytes each iteration.
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} {
// Write the _preBytes data into the tempBytes memory 32 bytes
// at a time.
mstore(mc, mload(cc))
}
// Add the length of _postBytes to the current length of tempBytes
// and store it as the new length in the first 32 bytes of the
// tempBytes memory.
length := mload(_postBytes)
mstore(tempBytes, add(length, mload(tempBytes)))
// Move the memory counter back from a multiple of 0x20 to the
// actual end of the _preBytes data.
mc := end
// Stop copying when the memory counter reaches the new combined
// length of the arrays.
end := add(mc, length)
for {
let cc := add(_postBytes, 0x20)
} lt(mc, end) {
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} {
mstore(mc, mload(cc))
}
// Update the free-memory pointer by padding our last write location
// to 32 bytes: add 31 bytes to the end of tempBytes to move to the
// next 32 byte block, then round down to the nearest multiple of
// 32. If the sum of the length of the two arrays is zero then add
// one before rounding down to leave a blank 32 bytes (the length block with 0).
mstore(
0x40,
and(
add(add(end, iszero(add(length, mload(_preBytes)))), 31),
not(31) // Round down to the nearest 32 bytes.
)
)
}
return tempBytes;
}
function slice(bytes memory _bytes, uint256 _start, uint256 _length)
internal
pure
returns (bytes memory)
{
require(_bytes.length >= (_start + _length));
bytes memory tempBytes;
assembly {
switch iszero(_length)
case 0 {
// Get a location of some free memory and store it in tempBytes as
// Solidity does for memory variables.
tempBytes := mload(0x40)
// The first word of the slice result is potentially a partial
// word read from the original array. To read it, we calculate
// the length of that partial word and start copying that many
// bytes into the array. The first word we copy will start with
// data we don't care about, but the last `lengthmod` bytes will
// land at the beginning of the contents of the new array. When
// we're done copying, we overwrite the full first word with
// the actual length of the slice.
let lengthmod := and(_length, 31)
// The multiplication in the next line is necessary
// because when slicing multiples of 32 bytes (lengthmod == 0)
// the following copy loop was copying the origin's length
// and then ending prematurely not copying everything it should.
let mc := add(
add(tempBytes, lengthmod),
mul(0x20, iszero(lengthmod))
)
let end := add(mc, _length)
for {
// The multiplication in the next line has the same exact purpose
// as the one above.
let cc := add(
add(
add(_bytes, lengthmod),
mul(0x20, iszero(lengthmod))
),
_start
)
} lt(mc, end) {
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} {
mstore(mc, mload(cc))
}
mstore(tempBytes, _length)
//update free-memory pointer
//allocating the array padded to 32 bytes like the compiler does now
mstore(0x40, and(add(mc, 31), not(31)))
}
//if we want a zero-length slice let's just return a zero-length array
default {
tempBytes := mload(0x40)
mstore(0x40, add(tempBytes, 0x20))
}
}
return tempBytes;
}
// Pad a bytes array to 32 bytes
function leftPad(bytes memory _bytes) internal pure returns (bytes memory) {
// may underflow if bytes.length < 32. Hence using SafeMath.sub
bytes memory newBytes = new bytes(SafeMath.sub(32, _bytes.length));
return concat(newBytes, _bytes);
}
function toBytes32(bytes memory b) internal pure returns (bytes32) {
require(b.length >= 32, "Bytes array should atleast be 32 bytes");
bytes32 out;
for (uint256 i = 0; i < 32; i++) {
out |= bytes32(b[i] & 0xFF) >> (i * 8);
}
return out;
}
function toBytes4(bytes memory b) internal pure returns (bytes4 result) {
assembly {
result := mload(add(b, 32))
}
}
function fromBytes32(bytes32 x) internal pure returns (bytes memory) {
bytes memory b = new bytes(32);
for (uint256 i = 0; i < 32; i++) {
b[i] = bytes1(uint8(uint256(x) / (2**(8 * (31 - i)))));
}
return b;
}
function fromUint(uint256 _num) internal pure returns (bytes memory _ret) {
_ret = new bytes(32);
assembly {
mstore(add(_ret, 32), _num)
}
}
function toUint(bytes memory _bytes, uint256 _start)
internal
pure
returns (uint256)
{
require(_bytes.length >= (_start + 32));
uint256 tempUint;
assembly {
tempUint := mload(add(add(_bytes, 0x20), _start))
}
return tempUint;
}
function toAddress(bytes memory _bytes, uint256 _start)
internal
pure
returns (address)
{
require(_bytes.length >= (_start + 20));
address tempAddress;
assembly {
tempAddress := div(
mload(add(add(_bytes, 0x20), _start)),
0x1000000000000000000000000
)
}
return tempAddress;
}
}
"
},
"contracts/common/lib/Common.sol": {
"content": "pragma solidity ^0.5.2;
import "./BytesLib.sol";
library Common {
function getV(bytes memory v, uint16 chainId) public pure returns (uint8) {
if (chainId > 0) {
return
uint8(
BytesLib.toUint(BytesLib.leftPad(v), 0) - (chainId * 2) - 8
);
} else {
return uint8(BytesLib.toUint(BytesLib.leftPad(v), 0));
}
}
//assemble the given address bytecode. If bytecode exists then the _addr is a contract.
function isContract(address _addr) public view returns (bool) {
uint256 length;
assembly {
//retrieve the size of the code on target address, this needs assembly
length := extcodesize(_addr)
}
return (length > 0);
}
// convert bytes to uint8
function toUint8(bytes memory _arg) public pure returns (uint8) {
return uint8(_arg[0]);
}
function toUint16(bytes memory _arg) public pure returns (uint16) {
return (uint16(uint8(_arg[0])) << 8) | uint16(uint8(_arg[1]));
}
}
"
},
"contracts/common/lib/ECVerify.sol": {
"content": "pragma solidity ^0.5.2;
library ECVerify {
function ecrecovery(bytes32 hash, uint[3] memory sig)
internal
pure
returns (address)
{
bytes32 r;
bytes32 s;
uint8 v;
assembly {
r := mload(sig)
s := mload(add(sig, 32))
v := byte(31, mload(add(sig, 64)))
}
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return address(0x0);
}
// https://github.com/ethereum/go-ethereum/issues/2053
if (v < 27) {
v += 27;
}
if (v != 27 && v != 28) {
return address(0x0);
}
// get address out of hash and signature
address result = ecrecover(hash, v, r, s);
// ecrecover returns zero on error
require(result != address(0x0));
return result;
}
function ecrecovery(bytes32 hash, bytes memory sig)
internal
pure
returns (address)
{
bytes32 r;
bytes32 s;
uint8 v;
if (sig.length != 65) {
return address(0x0);
}
assembly {
r := mload(add(sig, 32))
s := mload(add(sig, 64))
v := and(mload(add(sig, 65)), 255)
}
// https://github.com/ethereum/go-ethereum/issues/2053
if (v < 27) {
v += 27;
}
if (v != 27 && v != 28) {
return address(0x0);
}
// get address out of hash and signature
address result = ecrecover(hash, v, r, s);
// ecrecover returns zero on error
require(result != address(0x0));
return result;
}
function ecrecovery(bytes32 hash, uint8 v, bytes32 r, bytes32 s)
internal
pure
returns (address)
{
// get address out of hash and signature
address result = ecrecover(hash, v, r, s);
// ecrecover returns zero on error
require(result != address(0x0), "signature verification failed");
return result;
}
function ecverify(bytes32 hash, bytes memory sig, address signer)
internal
pure
returns (bool)
{
return signer == ecrecovery(hash, sig);
}
}
"
},
"contracts/common/lib/ExitPayloadReader.sol": {
"content": "pragma solidity 0.5.17;
import {RLPReader} from "./RLPReader.sol";
import {BytesLib} from "./BytesLib.sol";
library ExitPayloadReader {
using RLPReader for bytes;
using RLPReader for RLPReader.RLPItem;
uint8 constant WORD_SIZE = 32;
struct ExitPayload {
RLPReader.RLPItem[] data;
}
struct Receipt {
RLPReader.RLPItem[] data;
bytes raw;
uint256 logIndex;
}
struct Log {
RLPReader.RLPItem data;
RLPReader.RLPItem[] list;
}
struct LogTopics {
RLPReader.RLPItem[] data;
}
function toExitPayload(bytes memory data)
internal
pure
returns (ExitPayload memory)
{
RLPReader.RLPItem[] memory payloadData = data
.toRlpItem()
.toList();
return ExitPayload(payloadData);
}
function copy(uint src, uint dest, uint len) private pure {
if (len == 0) return;
// copy as many word sizes as possible
for (; len >= WORD_SIZE; len -= WORD_SIZE) {
assembly {
mstore(dest, mload(src))
}
src += WORD_SIZE;
dest += WORD_SIZE;
}
// left over bytes. Mask is used to remove unwanted bytes from the word
uint mask = 256 ** (WORD_SIZE - len) - 1;
assembly {
let srcpart := and(mload(src), not(mask)) // zero out src
let destpart := and(mload(dest), mask) // retrieve the bytes
mstore(dest, or(destpart, srcpart))
}
}
function getHeaderNumber(ExitPayload memory payload) internal pure returns(uint256) {
return payload.data[0].toUint();
}
function getBlockProof(ExitPayload memory payload) internal pure returns(bytes memory) {
return payload.data[1].toBytes();
}
function getBlockNumber(ExitPayload memory payload) internal pure returns(uint256) {
return payload.data[2].toUint();
}
function getBlockTime(ExitPayload memory payload) internal pure returns(uint256) {
return payload.data[3].toUint();
}
function getTxRoot(ExitPayload memory payload) internal pure returns(bytes32) {
return bytes32(payload.data[4].toUint());
}
function getReceiptRoot(ExitPayload memory payload) internal pure returns(bytes32) {
return bytes32(payload.data[5].toUint());
}
function getReceipt(ExitPayload memory payload) internal pure returns(Receipt memory receipt) {
receipt.raw = payload.data[6].toBytes();
RLPReader.RLPItem memory receiptItem = receipt.raw.toRlpItem();
if (receiptItem.isList()) {
// legacy tx
receipt.data = receiptItem.toList();
} else {
// pop first byte before parsting receipt
bytes memory typedBytes = receipt.raw;
bytes memory result = new bytes(typedBytes.length - 1);
uint256 srcPtr;
uint256 destPtr;
assembly {
srcPtr := add(33, typedBytes)
destPtr := add(0x20, result)
}
copy(srcPtr, destPtr, result.length);
receipt.data = result.toRlpItem().toList();
}
receipt.logIndex = getReceiptLogIndex(payload);
return receipt;
}
function getReceiptProof(ExitPayload memory payload) internal pure returns(bytes memory) {
return payload.data[7].toBytes();
}
function getBranchMaskAsBytes(ExitPayload memory payload) internal pure returns(bytes memory) {
return payload.data[8].toBytes();
}
function getBranchMaskAsUint(ExitPayload memory payload) internal pure returns(uint256) {
return payload.data[8].toUint();
}
function getReceiptLogIndex(ExitPayload memory payload) internal pure returns(uint256) {
return payload.data[9].toUint();
}
function getTx(ExitPayload memory payload) internal pure returns(bytes memory) {
return payload.data[10].toBytes();
}
function getTxProof(ExitPayload memory payload) internal pure returns(bytes memory) {
return payload.data[11].toBytes();
}
// Receipt methods
function toBytes(Receipt memory receipt) internal pure returns(bytes memory) {
return receipt.raw;
}
function getLog(Receipt memory receipt) internal pure returns(Log memory) {
RLPReader.RLPItem memory logData = receipt.data[3].toList()[receipt.logIndex];
return Log(logData, logData.toList());
}
// Log methods
function getEmitter(Log memory log) internal pure returns(address) {
return RLPReader.toAddress(log.list[0]);
}
function getTopics(Log memory log) internal pure returns(LogTopics memory) {
return LogTopics(log.list[1].toList());
}
function getData(Log memory log) internal pure returns(bytes memory) {
return log.list[2].toBytes();
}
function toRlpBytes(Log memory log) internal pure returns(bytes memory) {
return log.data.toRlpBytes();
}
// LogTopics methods
function getField(LogTopics memory topics, uint256 index) internal pure returns(RLPReader.RLPItem memory) {
return topics.data[index];
}
}"
},
"contracts/common/lib/Merkle.sol": {
"content": "pragma solidity ^0.5.2;
library Merkle {
function checkMembership(
bytes32 leaf,
uint256 index,
bytes32 rootHash,
bytes memory proof
) internal pure returns (bool) {
require(proof.length % 32 == 0, "Invalid proof length");
uint256 proofHeight = proof.length / 32;
// Proof of size n means, height of the tree is n+1.
// In a tree of height n+1, max #leafs possible is 2 ^ n
require(index < 2 ** proofHeight, "Leaf index is too big");
bytes32 proofElement;
bytes32 computedHash = leaf;
for (uint256 i = 32; i <= proof.length; i += 32) {
assembly {
proofElement := mload(add(proof, i))
}
if (index % 2 == 0) {
computedHash = keccak256(
abi.encodePacked(computedHash, proofElement)
);
} else {
computedHash = keccak256(
abi.encodePacked(proofElement, computedHash)
);
}
index = index / 2;
}
return computedHash == rootHash;
}
}
"
},
"contracts/common/lib/MerklePatriciaProof.sol": {
"content": "pragma solidity ^0.5.2;
import {RLPReader} from "./RLPReader.sol";
library MerklePatriciaProof {
/*
* @dev Verifies a merkle patricia proof.
* @param value The terminating value in the trie.
* @param encodedPath The path in the trie leading to value.
* @param rlpParentNodes The rlp encoded stack of nodes.
* @param root The root hash of the trie.
* @return The boolean validity of the proof.
*/
function verify(
bytes memory value,
bytes memory encodedPath,
bytes memory rlpParentNodes,
bytes32 root
) internal pure returns (bool) {
RLPReader.RLPItem memory item = RLPReader.toRlpItem(rlpParentNodes);
RLPReader.RLPItem[] memory parentNodes = RLPReader.toList(item);
bytes memory currentNode;
RLPReader.RLPItem[] memory currentNodeList;
bytes32 nodeKey = root;
uint256 pathPtr = 0;
bytes memory path = _getNibbleArray(encodedPath);
if (path.length == 0) {
return false;
}
for (uint256 i = 0; i < parentNodes.length; i++) {
if (pathPtr > path.length) {
return false;
}
currentNode = RLPReader.toRlpBytes(parentNodes[i]);
if (nodeKey != keccak256(currentNode)) {
return false;
}
currentNodeList = RLPReader.toList(parentNodes[i]);
if (currentNodeList.length == 17) {
if (pathPtr == path.length) {
if (
keccak256(RLPReader.toBytes(currentNodeList[16])) ==
keccak256(value)
) {
return true;
} else {
return false;
}
}
uint8 nextPathNibble = uint8(path[pathPtr]);
if (nextPathNibble > 16) {
return false;
}
nodeKey = bytes32(
RLPReader.toUintStrict(currentNodeList[nextPathNibble])
);
pathPtr += 1;
} else if (currentNodeList.length == 2) {
bytes memory nodeValue = RLPReader.toBytes(currentNodeList[0]);
uint256 traversed = _nibblesToTraverse(
nodeValue,
path,
pathPtr
);
//enforce correct nibble
bytes1 prefix = _getNthNibbleOfBytes(0, nodeValue);
if (pathPtr + traversed == path.length) {
//leaf node
if (
keccak256(RLPReader.toBytes(currentNodeList[1])) == keccak256(value) &&
(prefix == bytes1(uint8(2)) || prefix == bytes1(uint8(3)))
) {
return true;
} else {
return false;
}
}
//extension node
if (traversed == 0 || (prefix != bytes1(uint8(0)) && prefix != bytes1(uint8(1)))) {
return false;
}
pathPtr += traversed;
nodeKey = bytes32(RLPReader.toUintStrict(currentNodeList[1]));
} else {
return false;
}
}
}
function _nibblesToTraverse(
bytes memory encodedPartialPath,
bytes memory path,
uint256 pathPtr
) private pure returns (uint256) {
uint256 len;
// encodedPartialPath has elements that are each two hex characters (1 byte), but partialPath
// and slicedPath have elements that are each one hex character (1 nibble)
bytes memory partialPath = _getNibbleArray(encodedPartialPath);
bytes memory slicedPath = new bytes(partialPath.length);
// pathPtr counts nibbles in path
// partialPath.length is a number of nibbles
for (uint256 i = pathPtr; i < pathPtr + partialPath.length; i++) {
bytes1 pathNibble = path[i];
slicedPath[i - pathPtr] = pathNibble;
}
if (keccak256(partialPath) == keccak256(slicedPath)) {
len = partialPath.length;
} else {
len = 0;
}
return len;
}
// bytes b must be hp encoded
function _getNibbleArray(bytes memory b)
private
pure
returns (bytes memory)
{
bytes memory nibbles;
if (b.length > 0) {
uint8 offset;
uint8 hpNibble = uint8(_getNthNibbleOfBytes(0, b));
if (hpNibble == 1 || hpNibble == 3) {
nibbles = new bytes(b.length * 2 - 1);
bytes1 oddNibble = _getNthNibbleOfBytes(1, b);
nibbles[0] = oddNibble;
offset = 1;
} else {
nibbles = new bytes(b.length * 2 - 2);
offset = 0;
}
for (uint256 i = offset; i < nibbles.length; i++) {
nibbles[i] = _getNthNibbleOfBytes(i - offset + 2, b);
}
}
return nibbles;
}
function _getNthNibbleOfBytes(uint256 n, bytes memory str)
private
pure
returns (bytes1)
{
return
bytes1(
n % 2 == 0 ? uint8(str[n / 2]) / 0x10 : uint8(str[n / 2]) % 0x10
);
}
}"
},
"contracts/common/lib/PriorityQueue.sol": {
"content": "pragma solidity ^0.5.2;
import "openzeppelin-solidity/contracts/ownership/Ownable.sol";
import {SafeMath} from "openzeppelin-solidity/contracts/math/SafeMath.sol";
/**
* @title PriorityQueue
* @dev A priority queue implementation.
*/
contract PriorityQueue is Ownable {
using SafeMath for uint256;
uint256[] heapList;
uint256 public currentSize;
constructor() public {
heapList = [0];
}
/**
* @dev Inserts an element into the priority queue.
* @param _priority Priority to insert.
* @param _value Some additional value.
*/
function insert(uint256 _priority, uint256 _value) public onlyOwner {
uint256 element = (_priority << 128) | _value;
heapList.push(element);
currentSize = currentSize.add(1);
_percUp(currentSize);
}
/**
* @dev Returns the top element of the heap.
* @return The smallest element in the priority queue.
*/
function getMin() public view returns (uint256, uint256) {
return _splitElement(heapList[1]);
}
/**
* @dev Deletes the top element of the heap and shifts everything up.
* @return The smallest element in the priorty queue.
*/
function delMin() public onlyOwner returns (uint256, uint256) {
uint256 retVal = heapList[1];
heapList[1] = heapList[currentSize];
delete heapList[currentSize];
currentSize = currentSize.sub(1);
_percDown(1);
heapList.length = heapList.length.sub(1);
return _splitElement(retVal);
}
/**
* @dev Determines the minimum child of a given node in the tree.
* @param _index Index of the node in the tree.
* @return The smallest child node.
*/
function _minChild(uint256 _index) private view returns (uint256) {
if (_index.mul(2).add(1) > currentSize) {
return _index.mul(2);
} else {
if (heapList[_index.mul(2)] < heapList[_index.mul(2).add(1)]) {
return _index.mul(2);
} else {
return _index.mul(2).add(1);
}
}
}
/**
* @dev Bubbles the element at some index up.
*/
function _percUp(uint256 _index) private {
uint256 index = _index;
uint256 j = index;
uint256 newVal = heapList[index];
while (newVal < heapList[index.div(2)]) {
heapList[index] = heapList[index.div(2)];
index = index.div(2);
}
if (index != j) {
heapList[index] = newVal;
}
}
/**
* @dev Bubbles the element at some index down.
*/
function _percDown(uint256 _index) private {
uint256 index = _index;
uint256 j = index;
uint256 newVal = heapList[index];
uint256 mc = _minChild(index);
while (mc <= currentSize && newVal > heapList[mc]) {
heapList[index] = heapList[mc];
index = mc;
mc = _minChild(index);
}
if (index != j) {
heapList[index] = newVal;
}
}
/**
* @dev Split an element into its priority and value.
* @param _element Element to decode.
* @return A tuple containing the priority and value.
*/
function _splitElement(uint256 _element)
private
pure
returns (uint256, uint256)
{
uint256 priority = _element >> 128;
uint256 value = uint256(uint128(_element));
return (priority, value);
}
}
"
},
"contracts/common/lib/RLPEncode.sol": {
"content": "// Library for RLP encoding a list of bytes arrays.
// Modeled after ethereumjs/rlp (https://github.com/ethereumjs/rlp)
// [Very] modified version of Sam Mayo's library.
pragma solidity ^0.5.2;
import "./BytesLib.sol";
library RLPEncode {
// Encode an item (bytes memory)
function encodeItem(bytes memory self)
internal
pure
returns (bytes memory)
{
bytes memory encoded;
if (self.length == 1 && uint8(self[0] & 0xFF) < 0x80) {
encoded = new bytes(1);
encoded = self;
} else {
encoded = BytesLib.concat(encodeLength(self.length, 128), self);
}
return encoded;
}
// Encode a list of items
function encodeList(bytes[] memory self)
internal
pure
returns (bytes memory)
{
bytes memory encoded;
for (uint256 i = 0; i < self.length; i++) {
encoded = BytesLib.concat(encoded, encodeItem(self[i]));
}
return BytesLib.concat(encodeLength(encoded.length, 192), encoded);
}
// Hack to encode nested lists. If you have a list as an item passed here, included
// pass = true in that index. E.g.
// [item, list, item] --> pass = [false, true, false]
// function encodeListWithPasses(bytes[] memory self, bool[] pass) internal pure returns (bytes memory) {
// bytes memory encoded;
// for (uint i=0; i < self.length; i++) {
// if (pass[i] == true) {
// encoded = BytesLib.concat(encoded, self[i]);
// } else {
// encoded = BytesLib.concat(encoded, encodeItem(self[i]));
// }
// }
// return BytesLib.concat(encodeLength(encoded.length, 192), encoded);
// }
// Generate the prefix for an item or the entire list based on RLP spec
function encodeLength(uint256 L, uint256 offset)
internal
pure
returns (bytes memory)
{
if (L < 56) {
bytes memory prefix = new bytes(1);
prefix[0] = bytes1(uint8(L + offset));
return prefix;
} else {
// lenLen is the length of the hex representation of the data length
uint256 lenLen;
uint256 i = 0x1;
while (L / i != 0) {
le
Submitted on: 2025-10-13 18:27:56
Comments
Log in to comment.
No comments yet.