Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Session key module #99

Merged
merged 39 commits into from
Oct 31, 2024
Merged
Changes from 1 commit
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
9437387
feat: new session key module compiled
ly0va Oct 16, 2024
731073d
test: add some tests
ly0va Oct 16, 2024
1fd3731
test: forgot to push
ly0va Oct 16, 2024
9ea2a3a
fix: session key transaction
ly0va Oct 17, 2024
5a0c423
fix: install / uninstall
ly0va Oct 17, 2024
6feded2
fix: a bunch of bugs
ly0va Oct 17, 2024
bc05b52
feat: create mini test framework
ly0va Oct 18, 2024
c1fff2a
feat: big refactor and ERC20 tests
ly0va Oct 19, 2024
e4f922f
feat: more tests
ly0va Oct 20, 2024
d84713b
fix: reorder tests
ly0va Oct 20, 2024
0b84192
feat: add getters
ly0va Oct 21, 2024
b68ec0e
fix: ERC165 support
ly0va Oct 21, 2024
c135f4e
feat: properly separate calls and transfers
ly0va Oct 22, 2024
8acedfe
fix: better fee limits
ly0va Oct 22, 2024
ab9eb0b
feat: if -> require
ly0va Oct 23, 2024
42d54dd
feat: storage layout overhaul to comply with AA restrictions
ly0va Oct 23, 2024
75c7813
feat: store number of constraints
ly0va Oct 24, 2024
9e66f62
feat: make tests work using local node
ly0va Oct 25, 2024
4122801
test: revoke key and getters
ly0va Oct 25, 2024
1621a7a
chore: format and lint
ly0va Oct 28, 2024
8ed637b
Merge remote-tracking branch 'origin/main' into lyova-session-keys-mo…
ly0va Oct 28, 2024
adc1efd
feat: session state getter
ly0va Oct 28, 2024
8961895
feat: try to adapt sdk and gateway to the new interface
ly0va Oct 29, 2024
dfa3428
chore: format
ly0va Oct 29, 2024
3c18e57
fix: update addresses
ly0va Oct 29, 2024
b794dc0
fix: erc165
ly0va Oct 29, 2024
044e6f0
fix: pass hooks data
ly0va Oct 30, 2024
e30fac9
fix: serialize bigints in a message
ly0va Oct 30, 2024
2658c92
chore: split e2e and contract tests
ly0va Oct 30, 2024
ea6c590
fix: update addresses
ly0va Oct 30, 2024
7069b20
chore: fix lints
ly0va Oct 30, 2024
76bda4f
chore: cspell fix
ly0va Oct 30, 2024
6ab5a04
fix: update address
ly0va Oct 30, 2024
86d5df4
fix: erc165 again
ly0va Oct 30, 2024
ebb927a
fix: review
ly0va Oct 31, 2024
903acbd
docs: update docs
ly0va Oct 31, 2024
8a606f6
chore: fmt
ly0va Oct 31, 2024
84ec928
feat: add comments and refactor getters a bit
ly0va Oct 31, 2024
1a5d231
Merge branch 'main' into lyova-session-keys-module
MexicanAce Oct 31, 2024
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
Prev Previous commit
Next Next commit
fix: a bunch of bugs
ly0va committed Oct 17, 2024
commit 6feded275be60ff8ab1852524b96db470a5eeca1
6 changes: 3 additions & 3 deletions packages/contracts/src/ClaveAccount.sol
Original file line number Diff line number Diff line change
@@ -212,7 +212,9 @@ contract ClaveAccount is
) internal returns (bytes4 magicValue) {
if (transaction.signature.length == 65) {
(address signer, ) = ECDSA.tryRecover(signedHash, transaction.signature);
// TODO: move it lower so that validation hooks are run
if (signer == address(0)) {
return bytes4(0);
}
return _k1IsOwner(signer) ? ACCOUNT_VALIDATION_SUCCESS_MAGIC : bytes4(0);
}

@@ -226,14 +228,12 @@ contract ClaveAccount is

// Run validation hooks
bool hookSuccess = runValidationHooks(signedHash, transaction, hookData);
console.log("hook success");
if (!hookSuccess) {
console.log("failed hook validation");
return bytes4(0);
}

bool valid = _handleValidation(validator, signedHash, signature);
console.log("passed validation");

magicValue = valid ? ACCOUNT_VALIDATION_SUCCESS_MAGIC : bytes4(0);
}
6 changes: 5 additions & 1 deletion packages/contracts/src/validators/SessionKeyValidator.sol
Original file line number Diff line number Diff line change
@@ -229,6 +229,8 @@ library SessionLib {
function fill(SessionPolicy storage session, NewSession memory newSession) internal {
session.isOpen = true;
session.expiry = newSession.expiry;
session.feeLimit.isLimited = true;
session.feeLimit.limit = newSession.feeLimit;
for (uint256 i = 0; i < newSession.policies.length; i++) {
NewFunctionPolicy memory newFunctionPolicy = newSession.policies[i];
FunctionPolicy storage functionPolicy = session.policy[newFunctionPolicy.target][newFunctionPolicy.selector];
@@ -292,6 +294,7 @@ contract SessionKeyValidator is IHook, IValidationHook, IExecutionHook, IModuleV

function createSession(NewSession memory newSession) public {
require(_isInitialized(msg.sender), "Account not initialized");
require(newSession.signer != address(0), "Invalid signer");
uint256 sessionId = sessions[msg.sender].nextSessionId++;
sessions[msg.sender].sessionsBySigner[newSession.signer] = sessionId;
SessionLib.SessionPolicy storage session = sessions[msg.sender].sessionsById[sessionId];
@@ -376,7 +379,8 @@ contract SessionKeyValidator is IHook, IValidationHook, IExecutionHook, IModuleV
Transaction calldata transaction,
bytes calldata _hookData
) external {
(address recoveredAddress, ) = ECDSA.tryRecover(signedHash, transaction.signature);
(bytes memory signature, , ) = abi.decode(transaction.signature, (bytes, address, bytes[]));
(address recoveredAddress, ) = ECDSA.tryRecover(signedHash, signature);
uint256 sessionId = sessions[msg.sender].sessionsBySigner[recoveredAddress];
if (sessionId == 0) {
// This transaction was not signed by a session key,
44 changes: 39 additions & 5 deletions packages/contracts/test/SessionKeyTest.ts
Original file line number Diff line number Diff line change
@@ -92,7 +92,7 @@ describe.only("SessionKeyModule tests", function () {
{
target: sessionTarget,
selector: '0x00000000',
maxValuePerUse: parseEther("0.1"),
maxValuePerUse: parseEther("0.01"),
isValueLimited: false,
valueLimit: 0,
constraints: []
@@ -122,23 +122,26 @@ describe.only("SessionKeyModule tests", function () {
const sessionKeyModuleContract = await fixtures.getSessionKeyContract();
const sessionKeyModuleAddress = await sessionKeyModuleContract.getAddress();

console.log("sessionOwner", sessionOwner.address);
console.log("sessionKeyModuleAddress", sessionKeyModuleAddress);

const smartAccount = new SmartAccount({
payloadSigner: async (hash) => abiCoder.encode(
["bytes", "address", "bytes[]"],
[
sessionOwner.signingKey.sign(hash).serialized,
sessionKeyModuleAddress,
["0x"]
["0x"] // this array supplies data for hooks
]
),
address: proxyAccountAddress,
secret: fixtures.wallet.privateKey,
secret: sessionOwner.privateKey,
}, provider);

const aaTx = {
...await aaTxTemplate(),
to: sessionTarget,
value: parseEther("0.1"),
value: parseEther("0.01"),
gasLimit: 100_000_000n,
};
// aaTx.gasLimit = await provider.estimateGas(aaTx);
@@ -149,7 +152,38 @@ describe.only("SessionKeyModule tests", function () {
const tx = await provider.broadcastTransaction(signedTransaction);
await tx.wait();

expect(await provider.getBalance(sessionTarget)).to.equal(parseEther("0.1"), "session target should have received the funds");
expect(await provider.getBalance(sessionTarget)).to.equal(parseEther("0.01"), "session target should have received the funds");
});

it("should reject a session key transaction that goes over value limit", async () => {
const sessionKeyModuleContract = await fixtures.getSessionKeyContract();
const sessionKeyModuleAddress = await sessionKeyModuleContract.getAddress();

const smartAccount = new SmartAccount({
payloadSigner: async (hash) => abiCoder.encode(
["bytes", "address", "bytes[]"],
[
sessionOwner.signingKey.sign(hash).serialized,
sessionKeyModuleAddress,
["0x"] // this array supplies data for hooks
]
),
address: proxyAccountAddress,
secret: sessionOwner.privateKey,
}, provider);

const aaTx = {
...await aaTxTemplate(),
to: sessionTarget,
value: parseEther("0.02"),
gasLimit: 100_000_000n,
};
// aaTx.gasLimit = await provider.estimateGas(aaTx);

const signedTransaction = await smartAccount.signTransaction(aaTx);
assert(signedTransaction != null, "valid transaction to sign");

await expect(provider.broadcastTransaction(signedTransaction)).to.be.reverted;
});

});