transactions before execution.
- (MultiSigWallet.sol)
View Source: contracts/multisig/MultiSigWallet.sol
struct Transaction {
address destination,
uint256 value,
bytes data,
bool executed
}
Constants & Variables
uint256 public constant MAX_OWNER_COUNT;
mapping(uint256 => struct MultiSigWallet.Transaction) public transactions;
mapping(uint256 => mapping(address => bool)) public confirmations;
mapping(address => bool) public isOwner;
address[] public owners;
uint256 public required;
uint256 public transactionCount;
Events
event Confirmation(address indexed sender, uint256 indexed transactionId);
event Revocation(address indexed sender, uint256 indexed transactionId);
event Submission(uint256 indexed transactionId);
event Execution(uint256 indexed transactionId);
event ExecutionFailure(uint256 indexed transactionId);
event Deposit(address indexed sender, uint256 value);
event OwnerAddition(address indexed owner);
event OwnerRemoval(address indexed owner);
event RequirementChange(uint256 required);
- onlyWallet
- ownerDoesNotExist
- ownerExists
- transactionExists
- confirmed
- notConfirmed
- notExecuted
- notNull
- validRequirement
modifier onlyWallet() internal
modifier ownerDoesNotExist(address owner) internal
Arguments
Name | Type | Description |
---|---|---|
owner | address |
modifier ownerExists(address owner) internal
Arguments
Name | Type | Description |
---|---|---|
owner | address |
modifier transactionExists(uint256 transactionId) internal
Arguments
Name | Type | Description |
---|---|---|
transactionId | uint256 |
modifier confirmed(uint256 transactionId, address owner) internal
Arguments
Name | Type | Description |
---|---|---|
transactionId | uint256 | |
owner | address |
modifier notConfirmed(uint256 transactionId, address owner) internal
Arguments
Name | Type | Description |
---|---|---|
transactionId | uint256 | |
owner | address |
modifier notExecuted(uint256 transactionId) internal
Arguments
Name | Type | Description |
---|---|---|
transactionId | uint256 |
modifier notNull(address _address) internal
Arguments
Name | Type | Description |
---|---|---|
_address | address |
modifier validRequirement(uint256 ownerCount, uint256 _required) internal
Arguments
Name | Type | Description |
---|---|---|
ownerCount | uint256 | |
_required | uint256 |
- constructor()
- constructor(address[] _owners, uint256 _required)
- addOwner(address owner)
- removeOwner(address owner)
- replaceOwner(address owner, address newOwner)
- changeRequirement(uint256 _required)
- submitTransaction(address destination, uint256 value, bytes data)
- confirmTransaction(uint256 transactionId)
- revokeConfirmation(uint256 transactionId)
- executeTransaction(uint256 transactionId)
- external_call(address destination, uint256 value, uint256 dataLength, bytes data)
- isConfirmed(uint256 transactionId)
- addTransaction(address destination, uint256 value, bytes data)
- getConfirmationCount(uint256 transactionId)
- getTransactionCount(bool pending, bool executed)
- getOwners()
- getConfirmations(uint256 transactionId)
- getTransactionIds(uint256 from, uint256 to, bool pending, bool executed)
Fallback function allows to deposit ether.
function () external payable
Source Code
function() external payable {
if (msg.value > 0) emit Deposit(msg.sender, msg.value);
}
Contract constructor sets initial owners and required number of confirmations. *
function (address[] _owners, uint256 _required) public nonpayable validRequirement
Arguments
Name | Type | Description |
---|---|---|
_owners | address[] | List of initial owners. |
_required | uint256 | Number of required confirmations. |
Source Code
constructor(address[] memory _owners, uint256 _required)
public
validRequirement(_owners.length, _required)
{
for (uint256 i = 0; i < _owners.length; i++) {
require(!isOwner[_owners[i]] && _owners[i] != address(0));
isOwner[_owners[i]] = true;
}
owners = _owners;
required = _required;
}
Allows to add a new owner. Transaction has to be sent by wallet.
function addOwner(address owner) public nonpayable onlyWallet ownerDoesNotExist notNull validRequirement
Arguments
Name | Type | Description |
---|---|---|
owner | address | Address of new owner. |
Source Code
function addOwner(address owner)
public
onlyWallet
ownerDoesNotExist(owner)
notNull(owner)
validRequirement(owners.length + 1, required)
{
isOwner[owner] = true;
owners.push(owner);
emit OwnerAddition(owner);
}
Allows to remove an owner. Transaction has to be sent by wallet.
function removeOwner(address owner) public nonpayable onlyWallet ownerExists
Arguments
Name | Type | Description |
---|---|---|
owner | address | Address of owner. |
Source Code
function removeOwner(address owner) public onlyWallet ownerExists(owner) {
isOwner[owner] = false;
for (uint256 i = 0; i < owners.length - 1; i++)
if (owners[i] == owner) {
owners[i] = owners[owners.length - 1];
break;
}
owners.length -= 1;
if (required > owners.length) changeRequirement(owners.length);
emit OwnerRemoval(owner);
}
Allows to replace an owner with a new owner. Transaction has to be sent by wallet. *
function replaceOwner(address owner, address newOwner) public nonpayable onlyWallet ownerExists ownerDoesNotExist
Arguments
Name | Type | Description |
---|---|---|
owner | address | Address of owner to be replaced. |
newOwner | address | Address of new owner. |
Source Code
function replaceOwner(address owner, address newOwner)
public
onlyWallet
ownerExists(owner)
ownerDoesNotExist(newOwner)
{
for (uint256 i = 0; i < owners.length; i++)
if (owners[i] == owner) {
owners[i] = newOwner;
break;
}
isOwner[owner] = false;
isOwner[newOwner] = true;
emit OwnerRemoval(owner);
emit OwnerAddition(newOwner);
}
Allows to change the number of required confirmations. Transaction has to be sent by wallet. *
function changeRequirement(uint256 _required) public nonpayable onlyWallet validRequirement
Arguments
Name | Type | Description |
---|---|---|
_required | uint256 | Number of required confirmations. |
Source Code
function changeRequirement(uint256 _required)
public
onlyWallet
validRequirement(owners.length, _required)
{
required = _required;
emit RequirementChange(_required);
}
Allows an owner to submit and confirm a transaction. *
function submitTransaction(address destination, uint256 value, bytes data) public nonpayable
returns(transactionId uint256)
Arguments
Name | Type | Description |
---|---|---|
destination | address | Transaction target address. |
value | uint256 | Transaction ether value. |
data | bytes | Transaction data payload. * |
Returns
Returns transaction ID.
Source Code
function submitTransaction(
address destination,
uint256 value,
bytes memory data
) public returns (uint256 transactionId) {
transactionId = addTransaction(destination, value, data);
confirmTransaction(transactionId);
}
Allows an owner to confirm a transaction.
function confirmTransaction(uint256 transactionId) public nonpayable ownerExists transactionExists notConfirmed
Arguments
Name | Type | Description |
---|---|---|
transactionId | uint256 | Transaction ID. |
Source Code
function confirmTransaction(uint256 transactionId)
public
ownerExists(msg.sender)
transactionExists(transactionId)
notConfirmed(transactionId, msg.sender)
{
confirmations[transactionId][msg.sender] = true;
emit Confirmation(msg.sender, transactionId);
executeTransaction(transactionId);
}
Allows an owner to revoke a confirmation for a transaction.
function revokeConfirmation(uint256 transactionId) public nonpayable ownerExists confirmed notExecuted
Arguments
Name | Type | Description |
---|---|---|
transactionId | uint256 | Transaction ID. |
Source Code
function revokeConfirmation(uint256 transactionId)
public
ownerExists(msg.sender)
confirmed(transactionId, msg.sender)
notExecuted(transactionId)
{
confirmations[transactionId][msg.sender] = false;
emit Revocation(msg.sender, transactionId);
}
Allows anyone to execute a confirmed transaction.
function executeTransaction(uint256 transactionId) public nonpayable ownerExists confirmed notExecuted
Arguments
Name | Type | Description |
---|---|---|
transactionId | uint256 | Transaction ID. |
Source Code
function executeTransaction(uint256 transactionId)
public
ownerExists(msg.sender)
confirmed(transactionId, msg.sender)
notExecuted(transactionId)
{
if (isConfirmed(transactionId)) {
Transaction storage txn = transactions[transactionId];
txn.executed = true;
if (external_call(txn.destination, txn.value, txn.data.length, txn.data))
emit Execution(transactionId);
else {
emit ExecutionFailure(transactionId);
txn.executed = false;
}
}
}
Low level transaction execution. *
function external_call(address destination, uint256 value, uint256 dataLength, bytes data) internal nonpayable
returns(bool)
Arguments
Name | Type | Description |
---|---|---|
destination | address | The address of the Smart Contract to call. |
value | uint256 | The amout of rBTC to send w/ the transaction. |
dataLength | uint256 | The size of the payload. |
data | bytes | Length The size of the payload. |
Returns
Success or failure.
Source Code
function external_call(
address destination,
uint256 value,
uint256 dataLength,
bytes memory data
) internal returns (bool) {
bool result;
assembly {
let x := mload(0x40) /// "Allocate" memory for output (0x40 is where "free memory" pointer is stored by convention)
let d := add(data, 32) /// First 32 bytes are the padded length of data, so exclude that
result := call(
sub(gas, 34710), /// 34710 is the value that solidity is currently emitting
/// It includes callGas (700) + callVeryLow (3, to pay for SUB) + callValueTransferGas (9000) +
/// callNewAccountGas (25000, in case the destination address does not exist and needs creating)
destination,
value,
d,
dataLength, /// Size of the input (in bytes) - this is what fixes the padding problem
x,
0 /// Output is ignored, therefore the output size is zero
)
}
return result;
}
Returns the confirmation status of a transaction.
function isConfirmed(uint256 transactionId) public view
returns(bool)
Arguments
Name | Type | Description |
---|---|---|
transactionId | uint256 | Transaction ID. |
Returns
Confirmation status.
Source Code
function isConfirmed(uint256 transactionId) public view returns (bool) {
uint256 count = 0;
for (uint256 i = 0; i < owners.length; i++) {
if (confirmations[transactionId][owners[i]]) count += 1;
if (count == required) return true;
}
return false;
}
Adds a new transaction to the transaction mapping, if transaction does not exist yet. *
function addTransaction(address destination, uint256 value, bytes data) internal nonpayable notNull
returns(transactionId uint256)
Arguments
Name | Type | Description |
---|---|---|
destination | address | Transaction target address. |
value | uint256 | Transaction ether value. |
data | bytes | Transaction data payload. * |
Returns
Returns transaction ID.
Source Code
function addTransaction(
address destination,
uint256 value,
bytes memory data
) internal notNull(destination) returns (uint256 transactionId) {
transactionId = transactionCount;
transactions[transactionId] = Transaction({
destination: destination,
value: value,
data: data,
executed: false
});
transactionCount += 1;
emit Submission(transactionId);
}
Get the number of confirmations of a transaction.
function getConfirmationCount(uint256 transactionId) public view
returns(count uint256)
Arguments
Name | Type | Description |
---|---|---|
transactionId | uint256 | Transaction ID. |
Returns
Number of confirmations.
Source Code
function getConfirmationCount(uint256 transactionId) public view returns (uint256 count) {
for (uint256 i = 0; i < owners.length; i++)
if (confirmations[transactionId][owners[i]]) count += 1;
}
Get the total number of transactions after filers are applied.
function getTransactionCount(bool pending, bool executed) public view
returns(count uint256)
Arguments
Name | Type | Description |
---|---|---|
pending | bool | Include pending transactions. |
executed | bool | Include executed transactions. |
Returns
Total number of transactions after filters are applied.
Source Code
function getTransactionCount(bool pending, bool executed) public view returns (uint256 count) {
for (uint256 i = 0; i < transactionCount; i++)
if ((pending && !transactions[i].executed) || (executed && transactions[i].executed))
count += 1;
}
Get the list of owners.
function getOwners() public view
returns(address[])
Source Code
function getOwners() public view returns (address[] memory) {
return owners;
}
Get the array with owner addresses, which confirmed transaction.
function getConfirmations(uint256 transactionId) public view
returns(_confirmations address[])
Arguments
Name | Type | Description |
---|---|---|
transactionId | uint256 | Transaction ID. |
Returns
Returns array of owner addresses.
Source Code
function getConfirmations(uint256 transactionId)
public
view
returns (address[] memory _confirmations)
{
address[] memory confirmationsTemp = new address[](owners.length);
uint256 count = 0;
uint256 i;
for (i = 0; i < owners.length; i++)
if (confirmations[transactionId][owners[i]]) {
confirmationsTemp[count] = owners[i];
count += 1;
}
_confirmations = new address[](count);
for (i = 0; i < count; i++) _confirmations[i] = confirmationsTemp[i];
}
Get the list of transaction IDs in defined range. *
function getTransactionIds(uint256 from, uint256 to, bool pending, bool executed) public view
returns(_transactionIds uint256[])
Arguments
Name | Type | Description |
---|---|---|
from | uint256 | Index start position of transaction array. |
to | uint256 | Index end position of transaction array. |
pending | bool | Include pending transactions. |
executed | bool | Include executed transactions. * |
Returns
Returns array of transaction IDs.
Source Code
function getTransactionIds(
uint256 from,
uint256 to,
bool pending,
bool executed
) public view returns (uint256[] memory _transactionIds) {
uint256[] memory transactionIdsTemp = new uint256[](transactionCount);
uint256 count = 0;
uint256 i;
for (i = 0; i < transactionCount; i++)
if ((pending && !transactions[i].executed) || (executed && transactions[i].executed)) {
transactionIdsTemp[count] = i;
count += 1;
}
_transactionIds = new uint256[](to - from);
for (i = from; i < to; i++) _transactionIds[i - from] = transactionIdsTemp[i];
}
- Address
- Administered
- AdminRole
- AdvancedToken
- AdvancedTokenStorage
- Affiliates
- AffiliatesEvents
- ApprovalReceiver
- BProPriceFeed
- CheckpointsShared
- Constants
- Context
- DevelopmentFund
- DummyContract
- EnumerableAddressSet
- EnumerableBytes32Set
- EnumerableBytes4Set
- ERC20
- ERC20Detailed
- ErrorDecoder
- Escrow
- EscrowReward
- FeedsLike
- FeesEvents
- FeeSharingCollector
- FeeSharingCollectorProxy
- FeeSharingCollectorStorage
- FeesHelper
- FourYearVesting
- FourYearVestingFactory
- FourYearVestingLogic
- FourYearVestingStorage
- GenericTokenSender
- GovernorAlpha
- GovernorVault
- IApproveAndCall
- IChai
- IContractRegistry
- IConverterAMM
- IERC1820Registry
- IERC20_
- IERC20
- IERC777
- IERC777Recipient
- IERC777Sender
- IFeeSharingCollector
- IFourYearVesting
- IFourYearVestingFactory
- IFunctionsList
- ILiquidityMining
- ILiquidityPoolV1Converter
- ILoanPool
- ILoanToken
- ILoanTokenLogicBeacon
- ILoanTokenLogicModules
- ILoanTokenLogicProxy
- ILoanTokenModules
- ILoanTokenWRBTC
- ILockedSOV
- IMoCState
- IModulesProxyRegistry
- Initializable
- InterestUser
- IPot
- IPriceFeeds
- IPriceFeedsExt
- IProtocol
- IRSKOracle
- ISovryn
- ISovrynSwapNetwork
- IStaking
- ISwapsImpl
- ITeamVesting
- ITimelock
- IV1PoolOracle
- IVesting
- IVestingFactory
- IVestingRegistry
- IWrbtc
- IWrbtcERC20
- LenderInterestStruct
- LiquidationHelper
- LiquidityMining
- LiquidityMiningConfigToken
- LiquidityMiningProxy
- LiquidityMiningStorage
- LoanClosingsEvents
- LoanClosingsLiquidation
- LoanClosingsRollover
- LoanClosingsShared
- LoanClosingsWith
- LoanClosingsWithoutInvariantCheck
- LoanInterestStruct
- LoanMaintenance
- LoanMaintenanceEvents
- LoanOpenings
- LoanOpeningsEvents
- LoanParamsStruct
- LoanSettings
- LoanSettingsEvents
- LoanStruct
- LoanToken
- LoanTokenBase
- LoanTokenLogicBeacon
- LoanTokenLogicLM
- LoanTokenLogicProxy
- LoanTokenLogicStandard
- LoanTokenLogicStorage
- LoanTokenLogicWrbtc
- LoanTokenSettingsLowerAdmin
- LockedSOV
- MarginTradeStructHelpers
- Medianizer
- ModuleCommonFunctionalities
- ModulesCommonEvents
- ModulesProxy
- ModulesProxyRegistry
- MultiSigKeyHolders
- MultiSigWallet
- Mutex
- Objects
- OrderStruct
- OrigingVestingCreator
- OriginInvestorsClaim
- Ownable
- Pausable
- PausableOz
- PreviousLoanToken
- PreviousLoanTokenSettingsLowerAdmin
- PriceFeedRSKOracle
- PriceFeeds
- PriceFeedsLocal
- PriceFeedsMoC
- PriceFeedV1PoolOracle
- ProtocolAffiliatesInterface
- ProtocolLike
- ProtocolSettings
- ProtocolSettingsEvents
- ProtocolSettingsLike
- ProtocolSwapExternalInterface
- ProtocolTokenUser
- Proxy
- ProxyOwnable
- ReentrancyGuard
- RewardHelper
- RSKAddrValidator
- SafeERC20
- SafeMath
- SafeMath96
- setGet
- SharedReentrancyGuard
- SignedSafeMath
- SOV
- sovrynProtocol
- StakingAdminModule
- StakingGovernanceModule
- StakingInterface
- StakingProxy
- StakingRewards
- StakingRewardsProxy
- StakingRewardsStorage
- StakingShared
- StakingStakeModule
- StakingStorageModule
- StakingStorageShared
- StakingVestingModule
- StakingWithdrawModule
- State
- SwapsEvents
- SwapsExternal
- SwapsImplLocal
- SwapsImplSovrynSwap
- SwapsUser
- TeamVesting
- Timelock
- TimelockHarness
- TimelockInterface
- TokenSender
- UpgradableProxy
- USDTPriceFeed
- Utils
- VaultController
- Vesting
- VestingCreator
- VestingFactory
- VestingLogic
- VestingRegistry
- VestingRegistry2
- VestingRegistry3
- VestingRegistryLogic
- VestingRegistryProxy
- VestingRegistryStorage
- VestingStorage
- WeightedStakingModule
- WRBTC