Skip to content
This repository has been archived by the owner on Mar 12, 2024. It is now read-only.

Payable vouchers #47

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion onchain/rollups/contracts/common/OutputEncoding.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,19 @@ library OutputEncoding {

/// @notice Encode a voucher.
/// @param destination The address that will receive the payload through a message call
/// @param value The amount of Wei to be passed along the call
/// @param payload The payload, which—in the case of Solidity contracts—encodes a function call
/// @return The encoded output
function encodeVoucher(
address destination,
uint256 value,
bytes calldata payload
) internal pure returns (bytes memory) {
return
abi.encodeWithSignature(
"Voucher(address,bytes)",
"Voucher(address,uint256,bytes)",
destination,
value,
payload
);
}
Expand Down
20 changes: 17 additions & 3 deletions onchain/rollups/contracts/dapp/CartesiDApp.sol
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,10 @@ contract CartesiDApp is

function executeVoucher(
address _destination,
uint256 _value,
bytes calldata _payload,
Proof calldata _proof
) external override nonReentrant returns (bool) {
) public override nonReentrant returns (bool) {
bytes32 epochHash;
uint256 firstInputIndex;
uint256 lastInputIndex;
Expand All @@ -121,7 +122,12 @@ contract CartesiDApp is
);

// reverts if proof isn't valid
_proof.validity.validateVoucher(_destination, _payload, epochHash);
_proof.validity.validateVoucher(
_destination,
_value,
_payload,
epochHash
);

uint256 voucherPosition = LibOutputValidation.getBitMaskPosition(
_proof.validity.outputIndexWithinInput,
Expand All @@ -134,7 +140,7 @@ contract CartesiDApp is
}

// execute voucher
(bool succ, ) = _destination.call(_payload);
(bool succ, ) = _destination.call{value: _value}(_payload);

// if properly executed, mark it as executed and emit event
if (succ) {
Expand All @@ -145,6 +151,14 @@ contract CartesiDApp is
return succ;
}

function executeVoucher(
address _destination,
bytes calldata _payload,
Proof calldata _proof
) external override returns (bool) {
return executeVoucher(_destination, 0, _payload, _proof);
}

function wasVoucherExecuted(
uint256 _inputIndex,
uint256 _outputIndexWithinInput
Expand Down
19 changes: 19 additions & 0 deletions onchain/rollups/contracts/dapp/ICartesiDApp.sol
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,25 @@ interface ICartesiDApp {
Proof calldata _proof
) external returns (bool);

/// @notice Try to execute a voucher.
///
/// Reverts if voucher was already successfully executed.
///
/// @param _destination The address that will receive the payload through a message call
/// @param _value The amount of Wei to be passed along the call
/// @param _payload The payload, which—in the case of Solidity contracts—encodes a function call
/// @param _proof The proof used to validate the voucher against
/// a claim submitted by the current consensus contract
/// @return Whether the execution was successful or not
/// @dev On a successful execution, emits a `VoucherExecuted` event.
/// Execution of already executed voucher will raise a `VoucherReexecutionNotAllowed` error.
function executeVoucher(
address _destination,
uint256 _value,
bytes calldata _payload,
Proof calldata _proof
) external returns (bool);

/// @notice Check whether a voucher has been executed.
/// @param _inputIndex The index of the input in the input box
/// @param _outputIndexWithinInput The index of output emitted by the input
Expand Down
4 changes: 3 additions & 1 deletion onchain/rollups/contracts/library/LibOutputValidation.sol
Original file line number Diff line number Diff line change
Expand Up @@ -215,17 +215,19 @@ library LibOutputValidation {
/// @notice Make sure the output proof is valid, otherwise revert.
/// @param v The output validity proof (D..J)
/// @param destination The address that will receive the payload through a message call
/// @param value The amount of Wei to be passed along the call
/// @param payload The payload, which—in the case of Solidity contracts—encodes a function call
/// @param epochHash The hash of the epoch in which the output was generated (K)
function validateVoucher(
OutputValidityProof calldata v,
address destination,
uint256 value,
bytes calldata payload,
bytes32 epochHash
) internal pure {
validateOutput(
v,
OutputEncoding.encodeVoucher(destination, payload),
OutputEncoding.encodeVoucher(destination, value, payload),
epochHash
);
}
Expand Down
13 changes: 11 additions & 2 deletions onchain/rollups/test/foundry/dapp/CartesiDApp.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ contract CartesiDAppTest is TestBase {

struct Voucher {
address destination;
uint256 value;
bytes payload;
}

Expand Down Expand Up @@ -592,11 +593,19 @@ contract CartesiDAppTest is TestBase {

function addVoucher(
address destination,
uint256 value,
bytes memory payload
) internal {
uint256 index = outputEnums.length;
outputEnums.push(LibServerManager.OutputEnum.VOUCHER);
vouchers[index] = Voucher(destination, payload);
vouchers[index] = Voucher(destination, value, payload);
}

function addVoucher(
address destination,
bytes memory payload
) internal {
addVoucher(destination, 0, payload);
}

function getVoucher(
Expand Down Expand Up @@ -644,7 +653,7 @@ contract CartesiDAppTest is TestBase {
function encodeVoucher(
Voucher calldata voucher
) external pure returns (bytes memory) {
return OutputEncoding.encodeVoucher(voucher.destination, voucher.payload);
return OutputEncoding.encodeVoucher(voucher.destination, voucher.value, voucher.payload);
}

function encodeNotice(
Expand Down
Loading