Skip to content

Commit

Permalink
[BOOST-4657] feat(evm): add claimant info to EventAction (#74)
Browse files Browse the repository at this point in the history
  • Loading branch information
sammccord authored Sep 9, 2024
2 parents 9a4d71b + cf1c775 commit 803b2e7
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 7 deletions.
20 changes: 20 additions & 0 deletions packages/evm/contracts/actions/AEventAction.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {AAction} from "contracts/actions/AAction.sol";
/// @dev This a minimal generic implementation that should be extended if additional functionality or customizations are required
/// @dev It is expected that the target contract has an externally accessible mint function whose selector
abstract contract AEventAction is AAction {
ActionClaimant internal actionClaimant;
ActionEvent[] internal actionEvents;

// Define Enums
Expand Down Expand Up @@ -47,12 +48,31 @@ abstract contract AEventAction is AAction {
Criteria actionParameter;
}

enum SignatureType {
EVENT,
FUNC
}

/// @notice The payload for identifying the action's claimaint
/// @param signatureType Whether claimaint is inferred from event or function
/// @param signature The 4 byte signature of the event or function
/// @param fieldIndex The index corresponding to claimant.
/// @param targetContract The address of the target contract
struct ActionClaimant {
SignatureType signatureType;
bytes4 signature;
uint8 fieldIndex;
address targetContract;
}

function getActionEventsCount() public view virtual returns (uint256);

function getActionEvent(uint256 index) public view virtual returns (ActionEvent memory);

function getActionEvents() public view virtual returns (ActionEvent[] memory);

function getActionClaimant() public view virtual returns (ActionClaimant memory);

/// @inheritdoc ACloneable
function getComponentInterface() public pure virtual override returns (bytes4) {
return type(AEventAction).interfaceId;
Expand Down
16 changes: 12 additions & 4 deletions packages/evm/contracts/actions/EventAction.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@ import {BoostError} from "contracts/shared/BoostError.sol";
import {AEventAction} from "contracts/actions/AEventAction.sol";

contract EventAction is AEventAction {
/// @notice The payload for initializing a ContractAction
/// @param target The target contract address
/// @param selector The selector for the function to be called
/// @param value The native token value to send with the function call
/// @notice The payload for initializing an EventAction
/// @param actionClaimant The payload describing how claimants are identified
/// @param actionEventOne The first event criteria to validate with
/// @param actionEventTwo The second event criteria to validate with
/// @param actionEventThree The third event criteria to validate with
/// @param actionEventFour The fourth event criteria to validate with
struct InitPayload {
ActionClaimant actionClaimant;
ActionEvent actionEventOne;
ActionEvent actionEventTwo;
ActionEvent actionEventThree;
Expand All @@ -31,6 +34,7 @@ contract EventAction is AEventAction {
}

function _initialize(InitPayload memory init_) internal virtual onlyInitializing {
actionClaimant = init_.actionClaimant;
actionEvents.push(init_.actionEventOne);
actionEvents.push(init_.actionEventTwo);
actionEvents.push(init_.actionEventThree);
Expand Down Expand Up @@ -61,4 +65,8 @@ contract EventAction is AEventAction {
function getActionEvents() public view virtual override returns (ActionEvent[] memory) {
return actionEvents;
}

function getActionClaimant() public view virtual override returns (ActionClaimant memory) {
return actionClaimant;
}
}
22 changes: 22 additions & 0 deletions packages/evm/test/actions/EventAction.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,17 @@ contract EventActionTest is Test {
action = _newActionClone();

// Define the InitPayload with an ActionEvent
AEventAction.ActionClaimant memory claimant;
AEventAction.Criteria memory criteria;
AEventAction.ActionEvent memory actionEventOne;

claimant = AEventAction.ActionClaimant({
signatureType: AEventAction.SignatureType.EVENT,
signature: bytes4(keccak256("Transfer(address,address,uint256)")),
fieldIndex: 0,
targetContract: address(mockAsset)
});

criteria = AEventAction.Criteria({
filterType: AEventAction.FilterType.EQUAL,
fieldType: AEventAction.PrimitiveType.ADDRESS,
Expand All @@ -38,6 +46,7 @@ contract EventActionTest is Test {
});

EventAction.InitPayload memory payload = EventAction.InitPayload({
actionClaimant: claimant,
actionEventOne: actionEventOne,
actionEventTwo: actionEventOne,
actionEventThree: actionEventOne,
Expand Down Expand Up @@ -108,6 +117,19 @@ contract EventActionTest is Test {
assertEq(retrievedEvent.eventSignature, bytes4(keccak256("Transfer(address,address,uint256)")));
}

/////////////////////////////////
// EventAction.getActionClaimant //
/////////////////////////////////

function testGetActionClaimant() public {
// Ensure the action event is retrieved correctly
AEventAction.ActionClaimant memory retrievedClaimant = action.getActionClaimant();

assertEq(retrievedClaimant.fieldIndex, 0);
assertEq(retrievedClaimant.signature, bytes4(keccak256("Transfer(address,address,uint256)")));
assertEq(retrievedClaimant.targetContract, address(mockAsset));
}

////////////////////////////////////
// EventAction.getComponentInterface //
////////////////////////////////////
Expand Down
32 changes: 30 additions & 2 deletions packages/sdk/src/Actions/EventAction.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
eventActionAbi,
readEventActionGetActionClaimant,
readEventActionGetActionEvent,
readEventActionGetActionEvents,
readEventActionGetActionEventsCount,
Expand All @@ -24,6 +25,7 @@ import type {
} from '../Deployable/Deployable';
import { DeployableTarget } from '../Deployable/DeployableTarget';
import {
type ActionClaimant,
type ActionEvent,
type Criteria,
type EventActionPayload,
Expand All @@ -50,6 +52,13 @@ export class EventAction extends DeployableTarget<
EventActionPayload,
typeof eventActionAbi
> {
/**
* @inheritdoc
*
* @public
* @readonly
* @type {*}
*/
public override readonly abi = eventActionAbi;
/**
* @inheritdoc
Expand Down Expand Up @@ -87,7 +96,7 @@ export class EventAction extends DeployableTarget<
// biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
...(params as any),
args: [index],
});
}) as Promise<ActionEvent>;
}

/**
Expand All @@ -106,7 +115,7 @@ export class EventAction extends DeployableTarget<
...this.optionallyAttachAccount(),
// biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
...(params as any),
});
}) as Promise<ActionEvent[]>;
}

/**
Expand All @@ -128,6 +137,25 @@ export class EventAction extends DeployableTarget<
});
}

/**
* Retrieves the payload describing how claimants can be identified from logs or function calls.
*
* @public
* @async
* @param {?ReadParams<typeof eventActionAbi, 'getActionClaimant'>} [params]
* @returns {Promise<ActionClaimant>}
*/
public async getActionClaimant(
params?: ReadParams<typeof eventActionAbi, 'getActionClaimant'>,
) {
return readEventActionGetActionClaimant(this._config, {
address: this.assertValidAddress(),
...this.optionallyAttachAccount(),
// biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
...(params as any),
}) as Promise<ActionClaimant>;
}

/**
* Executes a prepared event action
*
Expand Down
70 changes: 69 additions & 1 deletion packages/sdk/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,51 @@ export interface Criteria {
filterData: Hex;
}

/**
* Whether a given signature is an event or function
*
* @export
* @enum {number}
*/
export enum SignatureType {
EVENT = 0,
FUNC = 1,
}

/**
* The payload describing how claimants are identified
*
* @export
* @interface ActionClaimant
* @typedef {ActionClaimant}
*/
export interface ActionClaimant {
/**
* Whether claimaint is inferred from event or function
*
* @type {SignatureType}
*/
signatureType: SignatureType;
/**
* The 4 byte signature of the event or function
*
* @type {Hex}
*/
signature: Hex;
/**
* The index corresponding to claimant.
*
* @type {number}
*/
fieldIndex: number;
/**
* The address of the target contract
*
* @type {Address}
*/
targetContract: Address;
}

/**
* Object representation of an `ActionEvent` struct used in event actions.
*
Expand Down Expand Up @@ -361,6 +406,12 @@ export interface ActionEvent {
* @typedef {EventActionPayload}
*/
export interface EventActionPayload {
/**
* The payload describing how claimants are identified
*
* @type {ActionClaimant}
*/
actionClaimant: ActionClaimant;
/**
* The first action event.
*
Expand Down Expand Up @@ -398,13 +449,24 @@ export interface EventActionPayload {
* @returns {Hex}
*/
export const prepareEventActionPayload = ({
actionClaimant,
actionEventOne,
actionEventTwo,
actionEventThree,
actionEventFour,
}: EventActionPayload) => {
return encodeAbiParameters(
[
{
type: 'tuple',
name: 'actionClaimant',
components: [
{ type: 'uint8', name: 'signatureType' },
{ type: 'bytes4', name: 'signature' },
{ type: 'uint8', name: 'fieldIndex' },
{ type: 'address', name: 'targetContract' },
],
},
{
type: 'tuple',
name: 'actionEventOne',
Expand Down Expand Up @@ -482,7 +544,13 @@ export const prepareEventActionPayload = ({
],
},
],
[actionEventOne, actionEventTwo, actionEventThree, actionEventFour],
[
actionClaimant,
actionEventOne,
actionEventTwo,
actionEventThree,
actionEventFour,
],
);
};

Expand Down

0 comments on commit 803b2e7

Please sign in to comment.