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

fix: use signing key #77

Merged
merged 6 commits into from
Oct 4, 2024
Merged
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
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,14 @@ For help and support deploying and modifying this repo for your AVS, please:

1. Open a ticket via the intercom link at [support.eigenlayer.xyz](https://support.eigenlayer.xyz).
2. Include the necessary troubleshooting information for your environment:
* Local anvil testing:
* Redeploy your local test using `--revert-strings debug` flag via the following commands and retest: `npm run deploy:core-debug && npm run deploy:hello-world-debug`
* Include the full stacktrace from your error as a .txt file attachment.
* Create a minimal repo that demonstrates the behavior (fork or otherwise)
* Steps require to reproduce issue (compile and cause the error)
* Holesky testing:
* Ensure contracts are verified on Holesky. Eg `forge verify-contract --chain-id 17000 --num-of-optimizations 200 src/YourContract.sol:YourContract YOUR_CONTRACT_ADDRESS`
* Send us your transaction hash where your contract is failing. We will use Tenderly to debug (adjust gas limit) and/or cast to re-run the transaction (eg `cast call --trace "trace_replayTransaction(0xTransactionHash)"`).

- Local anvil testing:
- Recompile the contracts with the `--revert-strings debug` flag. Deploy the contracts again and retest.
Expand Down
39 changes: 19 additions & 20 deletions abis/HelloWorldServiceManager.json
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,25 @@
"internalType": "string"
}
],
"outputs": [],
"outputs": [
{
"name": "",
"type": "tuple",
"internalType": "struct IHelloWorldServiceManager.Task",
"components": [
{
"name": "name",
"type": "string",
"internalType": "string"
},
{
"name": "taskCreatedBlock",
"type": "uint32",
"internalType": "uint32"
}
]
}
],
"stateMutability": "nonpayable"
},
{
Expand Down Expand Up @@ -199,25 +217,6 @@
],
"stateMutability": "view"
},
{
"type": "function",
"name": "operatorHasMinimumWeight",
"inputs": [
{
"name": "operator",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "owner",
Expand Down
2 changes: 1 addition & 1 deletion contracts/script/utils/HelloWorldDeploymentLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ library HelloWorldDeploymentLib {
);
// Upgrade contracts
bytes memory upgradeCall = abi.encodeCall(
ECDSAStakeRegistry.initialize, (result.helloWorldServiceManager, 1, quorum)
ECDSAStakeRegistry.initialize, (result.helloWorldServiceManager, 0, quorum)
);
UpgradeableProxyLib.upgradeAndCall(result.stakeRegistry, stakeRegistryImpl, upgradeCall);
UpgradeableProxyLib.upgrade(result.helloWorldServiceManager, helloWorldServiceManagerImpl);
Expand Down
35 changes: 7 additions & 28 deletions contracts/src/HelloWorldServiceManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {ECDSAStakeRegistry} from "@eigenlayer-middleware/src/unaudited/ECDSAStak
import {IServiceManager} from "@eigenlayer-middleware/src/interfaces/IServiceManager.sol";
import {ECDSAUpgradeable} from
"@openzeppelin-upgrades/contracts/utils/cryptography/ECDSAUpgradeable.sol";
import {IERC1271Upgradeable} from "@openzeppelin-upgrades/contracts/interfaces/IERC1271Upgradeable.sol";
import {IHelloWorldServiceManager} from "./IHelloWorldServiceManager.sol";
import "@openzeppelin/contracts/utils/Strings.sol";

Expand Down Expand Up @@ -70,22 +71,8 @@ contract HelloWorldServiceManager is ECDSAServiceManagerBase, IHelloWorldService
function respondToTask(
Task calldata task,
uint32 referenceTaskIndex,
bytes calldata signature
) external onlyOperator {

// TODO Temporarily disabling this until we add in staking & delegation to the Operator scripts.
/** require(
operatorHasMinimumWeight(msg.sender),
string(abi.encodePacked(
"Operator does not have match the weight requirements. ",
"Operator weight=",
Strings.toString(ECDSAStakeRegistry(stakeRegistry).getLastCheckpointOperatorWeight(msg.sender)),
", Threshold weight=",
Strings.toString(ECDSAStakeRegistry(stakeRegistry).getLastCheckpointThresholdWeight())
))
);
*/

bytes memory signature
) external {
// check that the task is valid, hasn't been responsed yet, and is being responded in time
require(
keccak256(abi.encode(task)) == allTaskHashes[referenceTaskIndex],
Expand All @@ -99,23 +86,15 @@ contract HelloWorldServiceManager is ECDSAServiceManagerBase, IHelloWorldService
// The message that was signed
bytes32 messageHash = keccak256(abi.encodePacked("Hello, ", task.name));
bytes32 ethSignedMessageHash = messageHash.toEthSignedMessageHash();

// Recover the signer address from the signature
address signer = ethSignedMessageHash.recover(signature);

require(signer == msg.sender, "Message signer is not operator");
bytes4 magicValue = IERC1271Upgradeable.isValidSignature.selector;
if (!(magicValue == ECDSAStakeRegistry(stakeRegistry).isValidSignature(ethSignedMessageHash,signature))){
revert();
}

// updating the storage with task responses
allTaskResponses[msg.sender][referenceTaskIndex] = signature;

// emitting event
emit TaskResponded(referenceTaskIndex, task, msg.sender);
}

function operatorHasMinimumWeight(
address operator
) public view returns (bool) {
return ECDSAStakeRegistry(stakeRegistry).getLastCheckpointOperatorWeight(operator)
>= ECDSAStakeRegistry(stakeRegistry).getLastCheckpointThresholdWeight();
}
}
4 changes: 0 additions & 4 deletions contracts/src/IHelloWorldServiceManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@ interface IHelloWorldServiceManager {
uint32 taskIndex
) external view returns (bytes memory);

function operatorHasMinimumWeight(
address operator
) external view returns (bool);

function createNewTask(
string memory name
) external returns (Task memory);
Expand Down
23 changes: 18 additions & 5 deletions contracts/test/HelloWorldServiceManager.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -259,9 +259,15 @@ contract HelloWorldTaskManagerSetup is Test {

bytes memory signature = signWithSigningKey(operator, messageHash);

vm.prank(operator.key.addr);
address[] memory operators = new address[](1);
operators[0]=operator.key.addr;
bytes[] memory signatures = new bytes[](1);
signatures[0]= signature;

bytes memory signedTask = abi.encode(operators, signatures, uint32(block.number));

IHelloWorldServiceManager(helloWorldDeployment.helloWorldServiceManager).respondToTask(
task, referenceTaskIndex, signature
task, referenceTaskIndex, signedTask
);
}
}
Expand Down Expand Up @@ -415,9 +421,16 @@ contract RespondToTask is HelloWorldTaskManagerSetup {

bytes32 messageHash = keccak256(abi.encodePacked("Hello, ", taskName));
bytes32 ethSignedMessageHash = messageHash.toEthSignedMessageHash();
bytes memory signature = signWithOperatorKey(operators[0], ethSignedMessageHash); // TODO: Use signing key after changes to service manager
bytes memory signature = signWithSigningKey(operators[0], ethSignedMessageHash); // TODO: Use signing key after changes to service manager

address[] memory operatorsMem = new address[](1);
operatorsMem[0]=operators[0].key.addr;
bytes[] memory signatures = new bytes[](1);
signatures[0]= signature;

bytes memory signedTask = abi.encode(operatorsMem, signatures, uint32(block.number));

vm.prank(operators[0].key.addr);
sm.respondToTask(newTask, taskIndex, signature);
vm.roll(block.number+1);
sm.respondToTask(newTask, taskIndex, signedTask);
}
}
13 changes: 9 additions & 4 deletions operator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,19 @@ const signAndRespondToTask = async (taskIndex: number, taskCreatedBlock: number,
const messageBytes = ethers.getBytes(messageHash);
const signature = await wallet.signMessage(messageBytes);

console.log(
`Signing and responding to task ${taskIndex}`
)
console.log(`Signing and responding to task ${taskIndex}`);

const operators = [await wallet.getAddress()];
const signatures = [signature];
const signedTask = ethers.AbiCoder.defaultAbiCoder().encode(
["address[]", "bytes[]", "uint32"],
[operators, signatures, ethers.toBigInt(await provider.getBlockNumber())]
);

const tx = await helloWorldServiceManager.respondToTask(
{ name: taskName, taskCreatedBlock: taskCreatedBlock },
taskIndex,
signature
signedTask
);
await tx.wait();
console.log(`Responded to task.`);
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"deploy:core-debug": "cd contracts && forge script script/DeployEigenLayerCore.s.sol --rpc-url http://localhost:8545 --broadcast --revert-strings debug",
"deploy:hello-world-debug": "cd contracts && forge script script/HelloWorldDeployer.s.sol --rpc-url http://localhost:8545 --broadcast --revert-strings debug",
"build": "cd contracts && forge build",
"extract:abis": "npm run build && node utils/abis.js"
"extract:abis": "node utils/abis.js"
},
"dependencies": {
"dotenv": "^10.0.0",
Expand Down