-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into onboarding/util-calldata
- Loading branch information
Showing
16 changed files
with
684 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 3 additions & 3 deletions
6
...ethernaut-ai-ui/test/tasks/config.test.js → .../ethernaut-ai-ui/test/tasks/model.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
const types = require('ethernaut-common/src/validation/types') | ||
const output = require('ethernaut-common/src/ui/output') | ||
const storage = require('ethernaut-common/src/io/storage') | ||
const { setEnvVar } = require('ethernaut-common/src/io/env') | ||
|
||
require('../scopes/ai') | ||
.task('key', 'Sets the openai api key') | ||
.addParam('apiKey', 'The openai api key to use', undefined, types.string) | ||
.setAction(async ({ apiKey }, hre) => { | ||
try { | ||
const config = storage.readConfig() | ||
|
||
let summary = [] | ||
|
||
if (apiKey) { | ||
const currentKey = process.env.OPENAI_API_KEY | ||
setEnvVar('OPENAI_API_KEY', apiKey) | ||
summary.push(`- API Key set to ${apiKey} (was ${currentKey})`) | ||
} | ||
|
||
storage.saveConfig(config) | ||
|
||
if (summary.length === 0) { | ||
summary.push('No changes') | ||
} | ||
|
||
return output.resultBox(summary.join('\n')) | ||
} catch (err) { | ||
return output.errorBox(err) | ||
} | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
const output = require('ethernaut-common/src/ui/output') | ||
const types = require('ethernaut-common/src/validation/types') | ||
const { getContract } = require('../internal/get-contract') | ||
|
||
require('../scopes/interact') | ||
.task('standards', 'Checks if a contract address meets known token standards') | ||
.addPositionalParam( | ||
'address', | ||
'The contract address to check', | ||
undefined, | ||
types.address, | ||
) | ||
.setAction(async ({ address }, hre) => { | ||
try { | ||
const isERC165Supported = await checkERC165Support(address, hre) | ||
const erc20 = await checkERC20(address, hre) | ||
const erc721Support = isERC165Supported | ||
? await checkERC721(address, hre) | ||
: { erc721: false, metadata: false } | ||
const erc1155Support = isERC165Supported | ||
? await checkERC1155(address, hre) | ||
: { erc1155: false, metadata: false } | ||
|
||
let str = '' | ||
str += `Address: ${address}\n` | ||
str += 'Token Standards:\n' | ||
str += ` ERC-165 Supported: ${isERC165Supported ? 'Yes' : 'No'}\n` | ||
str += ` ERC-20: ${erc20 ? 'Yes' : 'No'}\n` | ||
|
||
// Always show ERC-721 status | ||
str += ` ERC-721: ${erc721Support.erc721 ? 'Yes' : 'No'}\n` | ||
str += ` ERC-721 Metadata: ${erc721Support.metadata ? 'Yes' : 'No'}\n` | ||
|
||
// Always show ERC-1155 status | ||
str += ` ERC-1155: ${erc1155Support.erc1155 ? 'Yes' : 'No'}\n` | ||
str += ` ERC-1155 Metadata: ${erc1155Support.metadata ? 'Yes' : 'No'}\n` | ||
|
||
return output.resultBox(str) | ||
} catch (err) { | ||
return output.errorBox(err) | ||
} | ||
}) | ||
|
||
async function checkERC165Support(address, hre) { | ||
try { | ||
const contract = await getContract('erc165', address, hre) | ||
return await contract.supportsInterface('0x01ffc9a7') // ERC-165 interface ID | ||
} catch (err) { | ||
return false | ||
} | ||
} | ||
|
||
async function checkERC20(address, hre) { | ||
try { | ||
const contract = await getContract('erc20', address, hre) | ||
|
||
// Check the existence of key ERC-20 functions | ||
await contract.totalSupply() | ||
await contract.balanceOf(address) | ||
|
||
// Additional checks for ERC-20 functions using their function signatures | ||
const functionsToCheck = [ | ||
'transfer', | ||
'approve', | ||
'allowance', | ||
'transferFrom', | ||
] | ||
|
||
// Check if these key ERC-20 functions exist in the contract | ||
for (const fn of functionsToCheck) { | ||
if (!contract.interface.getFunction(fn)) { | ||
return false // If any function is missing, it's not ERC-20 compliant | ||
} | ||
} | ||
|
||
return true | ||
} catch (err) { | ||
return false | ||
} | ||
} | ||
|
||
async function checkERC721(address, hre) { | ||
try { | ||
const contract = await getContract('erc721', address, hre) | ||
|
||
// Check if the contract supports the ERC-721 interface ID using ERC-165 | ||
const supportsInterface = await contract.supportsInterface('0x80ac58cd') // ERC-721 interface ID | ||
if (!supportsInterface) return false | ||
|
||
// Optionally, check if the contract supports ERC-721 Metadata extension | ||
const supportsMetadata = await contract.supportsInterface('0x5b5e139f') // ERC-721 Metadata interface ID | ||
|
||
// Return both ERC-721 and metadata support statuses | ||
return { erc721: supportsInterface, metadata: supportsMetadata } | ||
} catch (err) { | ||
return false | ||
} | ||
} | ||
|
||
async function checkERC1155(address, hre) { | ||
try { | ||
const contract = await getContract('erc1155', address, hre) | ||
|
||
// Check if the contract supports the ERC-1155 interface ID using ERC-165 | ||
const supportsInterface = await contract.supportsInterface('0xd9b67a26') // ERC-1155 interface ID | ||
if (!supportsInterface) return false | ||
|
||
// Optionally, check if the contract supports ERC-1155 Metadata URI extension | ||
const supportsMetadata = await contract.supportsInterface('0x0e89341c') // ERC-1155 Metadata URI interface ID | ||
|
||
// Return both ERC-1155 and metadata support statuses | ||
return { erc1155: supportsInterface, metadata: supportsMetadata } | ||
} catch (err) { | ||
return false | ||
} | ||
} |
64 changes: 64 additions & 0 deletions
64
packages/ethernaut-interact/test/fixture-projects/basic-project/contracts/ERC1155.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.24; | ||
|
||
import './ERC165.sol'; | ||
|
||
/// @title ERC1155 Interface | ||
interface IERC1155 is IERC165 { | ||
event TransferSingle( | ||
address indexed operator, | ||
address indexed from, | ||
address indexed to, | ||
uint256 id, | ||
uint256 value | ||
); | ||
|
||
function balanceOf( | ||
address account, | ||
uint256 id | ||
) external view returns (uint256); | ||
|
||
function safeTransferFrom( | ||
address from, | ||
address to, | ||
uint256 id, | ||
uint256 amount | ||
) external; | ||
} | ||
|
||
contract ERC1155 is ERC165, IERC1155 { | ||
mapping(uint256 => mapping(address => uint256)) private _balances; | ||
|
||
constructor() { | ||
_registerInterface(0xd9b67a26); // ERC-1155 Interface ID | ||
} | ||
|
||
function balanceOf( | ||
address account, | ||
uint256 id | ||
) public view override returns (uint256) { | ||
return _balances[id][account]; | ||
} | ||
|
||
function safeTransferFrom( | ||
address from, | ||
address to, | ||
uint256 id, | ||
uint256 amount | ||
) external override { | ||
require(to != address(0), 'ERC1155: transfer to the zero address'); | ||
require(_balances[id][from] >= amount, 'ERC1155: insufficient balance'); | ||
|
||
_balances[id][from] -= amount; | ||
_balances[id][to] += amount; | ||
|
||
emit TransferSingle(msg.sender, from, to, id, amount); | ||
} | ||
|
||
function _mint(address to, uint256 id, uint256 amount) internal { | ||
require(to != address(0), 'ERC1155: mint to the zero address'); | ||
_balances[id][to] += amount; | ||
|
||
emit TransferSingle(msg.sender, address(0), to, id, amount); | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
packages/ethernaut-interact/test/fixture-projects/basic-project/contracts/ERC165.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.24; | ||
|
||
/// @title ERC165 Interface | ||
interface IERC165 { | ||
function supportsInterface(bytes4 interfaceId) external view returns (bool); | ||
} | ||
|
||
contract ERC165 is IERC165 { | ||
mapping(bytes4 => bool) private _supportedInterfaces; | ||
|
||
constructor() { | ||
// Register ERC165 itself | ||
_registerInterface(0x01ffc9a7); | ||
} | ||
|
||
function supportsInterface( | ||
bytes4 interfaceId | ||
) external view override returns (bool) { | ||
return _supportedInterfaces[interfaceId]; | ||
} | ||
|
||
function _registerInterface(bytes4 interfaceId) internal { | ||
_supportedInterfaces[interfaceId] = true; | ||
} | ||
} |
Oops, something went wrong.