-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathBatchTxExecutor.sol
More file actions
118 lines (102 loc) · 3.75 KB
/
BatchTxExecutor.sol
File metadata and controls
118 lines (102 loc) · 3.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.7.3;
import {SafeMath} from "openzeppelin-contracts-3.4.1/contracts/math/SafeMath.sol";
import {Ownable} from "openzeppelin-contracts-3.4.1/contracts/access/Ownable.sol";
/**
* @title BatchTxExecutor
* @notice Utility that executes transactions in the provided white-list serially.
* Stable ordering of execution is not guaranteed.
*/
contract BatchTxExecutor is Ownable {
using SafeMath for uint256;
struct Transaction {
bool enabled;
address destination;
uint256 value;
bytes data;
}
event TransactionFailed(address indexed destination, uint256 index, bytes data, bytes reason);
Transaction[] public transactions;
/**
* @notice Computes and returns the total value for all enabled transactions.
*/
function totalValue() external view returns (uint256) {
uint256 fee;
for (uint256 i = 0; i < transactions.length; i++) {
Transaction storage t = transactions[i];
if (t.enabled) {
fee += t.value;
}
}
return fee;
}
/**
* @notice Executes all transactions marked enabled.
* If any transaction in the transaction list reverts, it returns false.
*/
function executeAll() external payable returns (bool) {
bool exeuctionSuccess = true;
for (uint256 i = 0; i < transactions.length; i++) {
Transaction storage t = transactions[i];
if (t.enabled) {
(bool result, bytes memory reason) = t.destination.call{value: t.value}(t.data);
if (!result) {
emit TransactionFailed(t.destination, i, t.data, reason);
exeuctionSuccess = false;
}
}
}
return exeuctionSuccess;
}
/**
* @notice Helper function to re-trigger specific transaction in case of failure.
* @param index Transaction to execute
*/
function checkExecution(uint256 index) external payable returns (bool) {
Transaction storage t = transactions[index];
(bool result, ) = t.destination.call{value: t.value}(t.data);
return result;
}
/**
* @notice Adds a transaction to the transaction list
* @param destination Address of contract destination
* @param data Transaction data payload
*/
function addTransaction(
address destination,
uint256 value,
bytes calldata data
) external onlyOwner {
transactions.push(
Transaction({enabled: true, destination: destination, value: value, data: data})
);
}
/**
* @param index Index of transaction to remove.
* Transaction ordering may have changed since adding.
*/
function removeTransaction(uint256 index) external onlyOwner {
require(index < transactions.length, "BatchTxExecutor: index out of bounds");
if (index < transactions.length - 1) {
transactions[index] = transactions[transactions.length - 1];
}
transactions.pop();
}
/**
* @param index Index of transaction. Transaction ordering may have changed since adding.
* @param enabled True for enabled, false for disabled.
*/
function setTransactionEnabled(uint256 index, bool enabled) external onlyOwner {
require(
index < transactions.length,
"BatchTxExecutor: index must be in range of stored tx list"
);
transactions[index].enabled = enabled;
}
/**
* @return Number of transactions, both enabled and disabled, in transactions list.
*/
function transactionsSize() external view returns (uint256) {
return transactions.length;
}
}