Skip to content

Commit 3ef1bf0

Browse files
committed
update Orchestrator
1 parent 9a940f3 commit 3ef1bf0

File tree

1 file changed

+47
-48
lines changed

1 file changed

+47
-48
lines changed

contracts/Orchestrator.sol

Lines changed: 47 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -44,21 +44,59 @@ contract Orchestrator is Ownable {
4444
function rebase()
4545
external
4646
{
47+
// only callable by EOA to prevent flashloan attacks
4748
require(msg.sender == tx.origin); // solhint-disable-line avoid-tx-origin
4849

50+
// call monetary policy rebase, always revert on failure
4951
policy.rebase();
5052

51-
for (uint i = 0; i < transactions.length; i++) {
52-
Transaction storage t = transactions[i];
53-
if (t.enabled) {
54-
bool result =
55-
externalCall(t.destination, t.data);
56-
if (!result) {
57-
emit TransactionFailed(t.destination, i, t.data);
58-
revert("Transaction Failed");
59-
}
53+
// call peripheral contracts, revert batch if out-of-gas or silent revert
54+
for (uint256 index = 0; index < transactions.length; index++) {
55+
_executePeripheralTransaction(index);
56+
}
57+
}
58+
59+
/**
60+
* @notice Get the revert message and code from a call.
61+
* @param index uint256 Index of the transaction.
62+
* @return success bool True if peripheral transaction was successful.
63+
* @return returnData bytes Return data.
64+
*/
65+
function _executePeripheralTransaction(uint256 index)
66+
internal
67+
returns (bool success, bytes memory returnData)
68+
{
69+
// declare storage reference
70+
Transaction memory transaction = transactions[index];
71+
72+
// return early if disabled
73+
if (!transaction.enabled) {
74+
return (success, returnData);
75+
}
76+
77+
// perform low level external call and forward 63/64 remaining gas
78+
(success) = address(transaction.destination).call(transaction.data);
79+
80+
// Check if any of the atomic transactions failed, if not, decode return data
81+
if (!success) {
82+
assembly {
83+
returndatacopy(returnData, 0, returndatasize)
84+
}
85+
if (returnData.length == 0) {
86+
// If revert reason is empty, it is either OOG error or silent revert so we revert the batch
87+
revert("Transaction reverted silently");
88+
} else {
89+
// Log any other revert and continue rebase execution
90+
emit TransactionFailed(
91+
transaction.destination,
92+
index,
93+
transaction.data
94+
);
6095
}
6196
}
97+
98+
// explicit return
99+
return (success, returnData);
62100
}
63101

64102
/**
@@ -116,42 +154,3 @@ contract Orchestrator is Ownable {
116154
{
117155
return transactions.length;
118156
}
119-
120-
/**
121-
* @dev wrapper to call the encoded transactions on downstream consumers.
122-
* @param destination Address of destination contract.
123-
* @param data The encoded data payload.
124-
* @return True on success
125-
*/
126-
function externalCall(address destination, bytes data)
127-
internal
128-
returns (bool)
129-
{
130-
bool result;
131-
assembly { // solhint-disable-line no-inline-assembly
132-
// "Allocate" memory for output
133-
// (0x40 is where "free memory" pointer is stored by convention)
134-
let outputAddress := mload(0x40)
135-
136-
// First 32 bytes are the padded length of data, so exclude that
137-
let dataAddress := add(data, 32)
138-
139-
result := call(
140-
// 34710 is the value that solidity is currently emitting
141-
// It includes callGas (700) + callVeryLow (3, to pay for SUB)
142-
// + callValueTransferGas (9000) + callNewAccountGas
143-
// (25000, in case the destination address does not exist and needs creating)
144-
sub(gas, 34710),
145-
146-
147-
destination,
148-
0, // transfer value in wei
149-
dataAddress,
150-
mload(data), // Size of the input, in bytes. Stored in position 0 of the array.
151-
outputAddress,
152-
0 // Output is ignored, therefore the output size is zero
153-
)
154-
}
155-
return result;
156-
}
157-
}

0 commit comments

Comments
 (0)