Skip to content

Commit

Permalink
Merge pull request #764 from rainlanguage/2024-08-10-rescale-balance
Browse files Browse the repository at this point in the history
2024 08 10 rescale balance
  • Loading branch information
hardyjosh authored Aug 11, 2024
2 parents 790cac8 + f14536c commit cef329e
Show file tree
Hide file tree
Showing 11 changed files with 467 additions and 213 deletions.
361 changes: 181 additions & 180 deletions .gas-snapshot

Large diffs are not rendered by default.

35 changes: 29 additions & 6 deletions src/concrete/ob/OrderBook.sol
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import {
CONTEXT_CALLING_CONTEXT_COLUMN,
CONTEXT_CALCULATIONS_COLUMN,
CONTEXT_VAULT_IO_BALANCE_DIFF,
CONTEXT_VAULT_IO_TOKEN_DECIMALS,
CONTEXT_VAULT_INPUTS_COLUMN,
CONTEXT_VAULT_IO_TOKEN,
CONTEXT_VAULT_OUTPUTS_COLUMN,
Expand Down Expand Up @@ -748,24 +749,30 @@ contract OrderBook is IOrderBookV4, IMetaV1_2, ReentrancyGuard, Multicall, Order
);

{
uint256 inputTokenVaultBalance = sVaultBalances[order.owner][order.validInputs[inputIOIndex].token][order
.validInputs[inputIOIndex].vaultId];
callingContext[CONTEXT_VAULT_INPUTS_COLUMN - 1] = LibUint256Array.arrayFrom(
uint256(uint160(order.validInputs[inputIOIndex].token)),
order.validInputs[inputIOIndex].decimals * 1e18,
order.validInputs[inputIOIndex].vaultId,
sVaultBalances[order.owner][order.validInputs[inputIOIndex].token][order.validInputs[inputIOIndex]
.vaultId],
LibFixedPointDecimalScale.scale18(
inputTokenVaultBalance, order.validInputs[inputIOIndex].decimals, 0
),
// Don't know the balance diff yet!
0
);
}

{
uint256 outputTokenVaultBalance = sVaultBalances[order.owner][order.validOutputs[outputIOIndex]
.token][order.validOutputs[outputIOIndex].vaultId];
callingContext[CONTEXT_VAULT_OUTPUTS_COLUMN - 1] = LibUint256Array.arrayFrom(
uint256(uint160(order.validOutputs[outputIOIndex].token)),
order.validOutputs[outputIOIndex].decimals * 1e18,
order.validOutputs[outputIOIndex].vaultId,
sVaultBalances[order.owner][order.validOutputs[outputIOIndex].token][order.validOutputs[outputIOIndex]
.vaultId],
LibFixedPointDecimalScale.scale18(
outputTokenVaultBalance, order.validOutputs[outputIOIndex].decimals, 0
),
// Don't know the balance diff yet!
0
);
Expand Down Expand Up @@ -854,8 +861,24 @@ contract OrderBook is IOrderBookV4, IMetaV1_2, ReentrancyGuard, Multicall, Order
/// @param orderIOCalculation The verbatim order IO calculation returned by
/// `_calculateOrderIO`.
function recordVaultIO(uint256 input, uint256 output, OrderIOCalculationV2 memory orderIOCalculation) internal {
orderIOCalculation.context[CONTEXT_VAULT_INPUTS_COLUMN][CONTEXT_VAULT_IO_BALANCE_DIFF] = input;
orderIOCalculation.context[CONTEXT_VAULT_OUTPUTS_COLUMN][CONTEXT_VAULT_IO_BALANCE_DIFF] = output;
unchecked {
orderIOCalculation.context[CONTEXT_VAULT_INPUTS_COLUMN][CONTEXT_VAULT_IO_BALANCE_DIFF] =
LibFixedPointDecimalScale.scale18(
input,
orderIOCalculation.context[CONTEXT_VAULT_INPUTS_COLUMN][CONTEXT_VAULT_IO_TOKEN_DECIMALS] / 1e18,
0
);
orderIOCalculation.context[CONTEXT_VAULT_OUTPUTS_COLUMN][CONTEXT_VAULT_IO_BALANCE_DIFF] =
LibFixedPointDecimalScale.scale18(
output,
orderIOCalculation.context[CONTEXT_VAULT_OUTPUTS_COLUMN][CONTEXT_VAULT_IO_TOKEN_DECIMALS] / 1e18,
// Round outputs diff up if the scaling causes a rounding error.
// This only happens if the token has more than 18 decimals.
// Generally it's safer to overestimate output than
// underestimate.
FLAG_ROUND_UP
);
}

if (input > 0) {
// IMPORTANT! THIS MATH MUST BE CHECKED TO AVOID OVERFLOW.
Expand Down
6 changes: 3 additions & 3 deletions src/generated/OrderBookSubParser.pointers.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
pragma solidity =0.8.25;

/// @dev Hash of the known bytecode.
bytes32 constant BYTECODE_HASH = bytes32(0xf8d804a6f741a21c63ef4bfe2330c4eeaee58c3ec6caaf63657f41e6d862f4a0);
bytes32 constant BYTECODE_HASH = bytes32(0x0c60cb3f7af79c229c38a06c1fed7cf23fb76e1177b7cad267b0a6eb4aff93e3);

/// @dev The hash of the meta that describes the contract.
bytes32 constant DESCRIBED_BY_META_HASH = bytes32(0x37096fdde7b025c34cf7d2774f97f0fbb7711051fe45d959b7d34acadc31e4ee);
bytes32 constant DESCRIBED_BY_META_HASH = bytes32(0x1dbcdb005e2031aff1a4acda69b478f09665c3414e7b2a72f96c0c3099a380a9);

/// @dev The parse meta that is used to lookup word definitions.
/// The structure of the parse meta is:
Expand All @@ -31,7 +31,7 @@ bytes32 constant DESCRIBED_BY_META_HASH = bytes32(0x37096fdde7b025c34cf7d2774f97
/// bit count of the previous bloom filter. If we reach the end of the bloom
/// filters then we have a miss.
bytes constant PARSE_META =
hex"01004800040040420206180010a00040003806204008040820840086010100000030088de69a165139fb02c9be1f14361d851dc13efa18bc2b16131296c8116682f50b6f6a660584c8d41c02582b1ad22c2f06bbcde61ea8967915b4f4091283156f0109ac301087b0c70398cd201f611967211923d122dd2b8317c02b171b3926a52035ccb90ea9bcef19d276fe0a865655075e0bc300d3b4e80f8316290de78f2e0c9fc5d509a7e6560427db4a";
hex"010f400000028002c04430408080100088204004040001c04122021002014400002204bf47e41a19b4d70efcb25710917c780d8a999e00070e0c1bf88d921681b49419da75e908a426f7079c5bad20ce2f881edef4a21492cb9c172eb0931504342f01f5e3e51cc18c8712e8d28313b32a0b21b6e80f02af2c090611d3b80c5121240906775105ed58f018fc66531ff92d2111def2391d669daf0f6787972275a57f0aaef47f03bd62390bccc2da";

/// @dev The build depth of the parser meta.

Expand Down
8 changes: 4 additions & 4 deletions src/lib/LibOrderBookSubParser.sol
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,13 @@ bytes constant WORD_CALCULATED_IO_RATIO = "calculated-io-ratio";
bytes constant WORD_INPUT_TOKEN = "input-token";
bytes constant WORD_INPUT_TOKEN_DECIMALS = "input-token-decimals";
bytes constant WORD_INPUT_VAULT_ID = "input-vault-id";
bytes constant WORD_INPUT_VAULT_BALANCE_BEFORE = "uint256-input-vault-before";
bytes constant WORD_INPUT_VAULT_BALANCE_INCREASE = "uint256-input-vault-increase";
bytes constant WORD_INPUT_VAULT_BALANCE_BEFORE = "input-vault-before";
bytes constant WORD_INPUT_VAULT_BALANCE_INCREASE = "input-vault-increase";
bytes constant WORD_OUTPUT_TOKEN = "output-token";
bytes constant WORD_OUTPUT_TOKEN_DECIMALS = "output-token-decimals";
bytes constant WORD_OUTPUT_VAULT_ID = "output-vault-id";
bytes constant WORD_OUTPUT_VAULT_BALANCE_BEFORE = "uint256-output-vault-before";
bytes constant WORD_OUTPUT_VAULT_BALANCE_DECREASE = "uint256-output-vault-decrease";
bytes constant WORD_OUTPUT_VAULT_BALANCE_BEFORE = "output-vault-before";
bytes constant WORD_OUTPUT_VAULT_BALANCE_DECREASE = "output-vault-decrease";

bytes constant WORD_DEPOSITOR = "depositor";
bytes constant WORD_DEPOSIT_TOKEN = "deposit-token";
Expand Down
189 changes: 189 additions & 0 deletions test/concrete/ob/OrderBook.clear.context.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
// SPDX-License-Identifier: CAL
pragma solidity =0.8.25;

import {OrderBookExternalRealTest} from "test/util/abstract/OrderBookExternalRealTest.sol";
import {LibTestAddOrder} from "test/util/lib/LibTestAddOrder.sol";
import {
OrderConfigV3,
OrderV3,
ActionV1,
ClearConfig,
SignedContextV1,
IO,
EvaluableV3
} from "rain.orderbook.interface/interface/IOrderBookV4.sol";
import {REVERTING_MOCK_BYTECODE} from "test/util/lib/LibTestConstants.sol";
import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";

import {Strings} from "openzeppelin-contracts/contracts/utils/Strings.sol";

contract OrderBookClearOrderContextTest is OrderBookExternalRealTest {
using Strings for address;
using Strings for uint256;

function testContextEmptyStack(
address alice,
address bob,
uint256 aliceInputVaultId,
uint256 aliceOutputVaultId,
uint256 bobInputVaultId,
uint256 bobOutputVaultId
) external {
vm.assume(alice != bob);

string memory usingWordsFrom = string.concat("using-words-from ", address(iSubParser).toHexString(), "\n");

bytes memory rainStringAlice = bytes(
string.concat(
usingWordsFrom,
"_ _:5 2;",
":ensure(equal-to(input-token() ",
address(iToken0).toHexString(),
") \"input token\"),",
":ensure(equal-to(input-token-decimals() 12) \"input token decimals\"),",
":ensure(equal-to(input-vault-id() ",
aliceInputVaultId.toHexString(),
") \"input token vault\"),",
":ensure(equal-to(input-vault-before() 0) \"input vault before\"),",
":ensure(equal-to(output-token() ",
address(iToken1).toHexString(),
") \"output token\"),",
":ensure(equal-to(output-token-decimals() 6) \"output token decimals\"),",
":ensure(equal-to(output-vault-id() ",
aliceOutputVaultId.toHexString(),
") \"output token vault\"),",
":ensure(equal-to(output-vault-before() 100) \"output vault before\"),",
":ensure(equal-to(orderbook() ",
address(iOrderbook).toHexString(),
") \"OrderBook\"),",
":ensure(equal-to(order-clearer() ",
address(this).toHexString(),
") \"clearer\"),",
":ensure(equal-to(order-owner() ",
alice.toHexString(),
") \"Alice\"),",
":ensure(equal-to(order-counterparty() ",
bob.toHexString(),
") \"Bob\"),",
":ensure(equal-to(calculated-io-ratio() 2) \"alice io ratio\"),",
":ensure(equal-to(output-vault-decrease() 1.5) \"alice output vault decrease\"),",
":ensure(equal-to(input-vault-increase() 3) \"alice input vault increase\"),",
":ensure(equal-to(calculated-max-output() 5) \"alice max output\");"
)
);

bytes memory rainStringBob = bytes(
string.concat(
string.concat(
usingWordsFrom,
"_ _:3 0.5;",
":ensure(equal-to(input-token() ",
address(iToken1).toHexString(),
") \"input token\"),",
":ensure(equal-to(input-token-decimals() 6) \"input token decimals\"),",
":ensure(equal-to(input-vault-id() ",
bobInputVaultId.toHexString(),
") \"input token vault\"),",
":ensure(equal-to(input-vault-before() 0) \"input vault before\"),",
":ensure(equal-to(output-token() ",
address(iToken0).toHexString(),
") \"output token\"),",
":ensure(equal-to(output-token-decimals() 12) \"output token decimals\"),",
":ensure(equal-to(output-vault-id() ",
bobOutputVaultId.toHexString(),
") \"output token vault\"),",
":ensure(equal-to(output-vault-before() 100) \"output vault before\"),",
":ensure(equal-to(orderbook() ",
address(iOrderbook).toHexString(),
") \"OrderBook\"),"
),
":ensure(equal-to(order-clearer() ",
address(this).toHexString(),
") \"clearer\"),",
":ensure(equal-to(order-owner() ",
bob.toHexString(),
") \"Bob\"),",
":ensure(equal-to(order-counterparty() ",
alice.toHexString(),
") \"Alice\"),",
":ensure(equal-to(calculated-io-ratio() 0.5) \"bob io ratio\"),",
":ensure(equal-to(output-vault-decrease() 3) \"bob output vault decrease\"),",
":ensure(equal-to(input-vault-increase() 1.5) \"bob input vault increase\"),",
":ensure(equal-to(calculated-max-output() 3) \"bob max output\");"
)
);

OrderConfigV3 memory configAlice;
{
IO[] memory validInputsAlice = new IO[](1);
validInputsAlice[0] = IO({token: address(iToken0), decimals: 12, vaultId: aliceInputVaultId});
IO[] memory validOutputsAlice = new IO[](1);
validOutputsAlice[0] = IO({token: address(iToken1), decimals: 6, vaultId: aliceOutputVaultId});
configAlice = OrderConfigV3({
evaluable: EvaluableV3({
bytecode: iParserV2.parse2(rainStringAlice),
interpreter: iInterpreter,
store: iStore
}),
validInputs: validInputsAlice,
validOutputs: validOutputsAlice,
nonce: 0,
secret: 0,
meta: ""
});
}
OrderConfigV3 memory configBob;
{
IO[] memory validInputsBob = new IO[](1);
validInputsBob[0] = IO({token: address(iToken1), decimals: 6, vaultId: bobInputVaultId});

IO[] memory validOutputsBob = new IO[](1);
validOutputsBob[0] = IO({token: address(iToken0), decimals: 12, vaultId: bobOutputVaultId});

configBob = OrderConfigV3({
evaluable: EvaluableV3({bytecode: iParserV2.parse2(rainStringBob), interpreter: iInterpreter, store: iStore}),
validInputs: validInputsBob,
validOutputs: validOutputsBob,
nonce: 0,
secret: 0,
meta: ""
});
}

vm.mockCall(
configAlice.validOutputs[0].token,
abi.encodeWithSelector(IERC20.transferFrom.selector, alice, address(iOrderbook)),
abi.encode(true)
);
vm.mockCall(
configBob.validOutputs[0].token,
abi.encodeWithSelector(IERC20.transferFrom.selector, bob, address(iOrderbook)),
abi.encode(true)
);

OrderV3 memory orderAlice =
OrderV3(alice, configAlice.evaluable, configAlice.validInputs, configAlice.validOutputs, configAlice.nonce);
OrderV3 memory orderBob =
OrderV3(bob, configBob.evaluable, configBob.validInputs, configBob.validOutputs, configBob.nonce);

vm.prank(alice);
iOrderbook.addOrder2(configAlice, new ActionV1[](0));

vm.prank(alice);
iOrderbook.deposit2(
configAlice.validOutputs[0].token, configAlice.validOutputs[0].vaultId, 100e6, new ActionV1[](0)
);

vm.prank(bob);
iOrderbook.addOrder2(configBob, new ActionV1[](0));

vm.prank(bob);
iOrderbook.deposit2(
configBob.validOutputs[0].token, configBob.validOutputs[0].vaultId, 100e12, new ActionV1[](0)
);

iOrderbook.clear2(
orderAlice, orderBob, ClearConfig(0, 0, 0, 0, 0, 0), new SignedContextV1[](0), new SignedContextV1[](0)
);
}
}
Loading

0 comments on commit cef329e

Please sign in to comment.