Prepared by:
HALBORN
Last Updated 04/26/2024
Date of Engagement by: August 15th, 2022 - August 20th, 2022
100% of all REPORTED Findings have been addressed
All findings
4
Critical
0
High
0
Medium
1
Low
3
Informational
0
Seascape engaged Halborn to conduct a security audit on their smart contracts beginning on August 15th, 2022 and ending on August 20th, 2022. The security assessment was scoped to the smart contract provided in the GitHub repository blocklords3d/smartcontracts/
The team at Halborn was provided a week for the engagement and assigned two full-time security engineers to audit the security of the smart contract. The security engineers are blockchain and smart-contract security experts with advanced penetration testing, smart-contract hacking, and deep knowledge of multiple blockchain protocols.
The purpose of this audit is to:
Ensure that smart contract functions operate as intended
Identify potential security issues with the smart contracts
In summary, Halborn identified some security risks that were addressed by the Seascape team
.
Halborn performed a combination of manual and automated security testing to balance efficiency, timeliness, practicality, and accuracy in regard to the scope of this audit. While manual testing is recommended to uncover flaws in logic, process, and implementation; automated testing techniques help enhance coverage of the code and can quickly identify items that do not follow the security best practices. The following phases and associated tools were used during the audit:
Research into architecture and purpose
Smart contract manual code review and walkthrough
Graphing out functionality and contract logic/connectivity/functions (solgraph
)
Manual assessment of use and safety for the critical Solidity variables and functions in scope to identify any arithmetic related vulnerability classes
Manual testing by custom scripts
Scanning of solidity files for vulnerabilities, security hotspots or bugs. (MythX
)
Static Analysis of security for scoped contract, and imported functions. (Slither
)
Testnet deployment (Brownie
, Remix IDE
)
IN-SCOPE: The security assessment was scoped to the following smart contracts
ImportExportManager.sol
ImportExportElasticNft.sol
1st Commit ID: f64fa27b972cd6697b8c851b5586b455c165aec6
2nd Commit ID: 5cda6c52f94583c4d44d84e1f36770f30f984246
Critical
0
High
0
Medium
1
Low
3
Informational
0
Impact x Likelihood
HAL-01
HAL-02
HAL-03
HAL-04
Security analysis | Risk level | Remediation Date |
---|---|---|
UNUSABLE CONTRACT | Medium | Solved - 09/19/2022 |
UNDEFINED VARIABLES ARE USED | Low | Solved - 09/19/2022 |
UNDEFINED IMPORTS ARE USED | Low | Solved - 09/19/2022 |
MISSING ZERO ADDRESS CHECKS | Low | Solved - 09/19/2022 |
// Medium
The ImportExportElasticNft.sol
smart contract constructor initializes the nft
variable to the same value. This cause nft
value to be equal to 0x0000000000000000000000000000000000000000
. Once deployed, this means that the contract cannot be used since there is no way to modify this variable.
constructor(address nft) SecureContract(true, true) {
nft = _nft;
owner = msg.sender;
verifier = msg.sender;
}
To replicate this issue:
elastic = await (await (await hre.ethers.getContractFactory("ImportExportElasticNft"))
.deploy(block.address)).deployed();
console.log('[+] nft addr: ' + await elastic.nft());
Elastic Testing
[+] nft add: 0x0000000000000000000000000000000000000000
SOLVED: The SeaScape team
now assigns correctly the _nft
parameter to the nft
state variable.
// Low
The ImportExportElasticNft.sol
smart contract uses undefined variables, resulting in contracts which do not compile.
nftExportNonce
(ImportExportElasticNft.sol#59,65)SOLVED: The SeaScape team
has implemented and declared the mapping nftExportNonce
.
// Low
The ImportExportElasticNft.sol
smart contract uses undefined castings referring to other contracts. The name of these contracts is not correct.
Blocklords
(ImportExportElasticNft.sol#46,47,67)SOLVED: The SeaScape team
has renamed the Blocklord
contract to BlockLords
to correct this import.
// Low
It has been detected that some functions, such as exportNft()
, and exportToken()
of the smart contracts, are missing address validation. Every input address should be checked not to be zero, especially the ones that could lead to rendering the contract unusable, lock tokens, etc. This is considered a best practice.
function exportNft(address nft, uint nftId, uint8 _v, bytes32 _r, bytes32 _s) external {
require(supportedNfts[nft], "unsupported token");
/// Validation of quality
/// message is generated as owner + amount + last time stamp + quality
bytes memory _prefix = "\x19Ethereum Signed Message:\n32";
bytes32 _messageNoPrefix =
keccak256(abi.encodePacked(msg.sender, nft, address(this), block.chainid, nftId, nftExportNonce[msg.sender]));
bytes32 _message = keccak256(abi.encodePacked(_prefix, _messageNoPrefix));
address _recover = ecrecover(_message, _v, _r, _s);
require(_recover == verifier, "verification failed");
nftExportNonce[msg.sender]++;
address accountHodler = accountHodlerOf(msg.sender);
if (address(accountHodler).codehash == 0) {
require(deploy(accountHodler, msg.sender), "Failed to deploy the contract");
AccountHodler(accountHodler).initialize(owner);
}
AccountHodler(accountHodler).exportNft(nft, msg.sender, nftId);
}
function exportToken(address token, uint amount, uint fee, uint8 _v, bytes32 _r, bytes32 _s) external {
require(supportedTokens[token], "unsupported token");
/// Validation of quality
/// message is generated as owner + amount + last time stamp + quality
bytes memory _prefix = "\x19Ethereum Signed Message:\n32";
bytes32 _messageNoPrefix =
keccak256(abi.encodePacked(msg.sender, token, address(this), block.chainid, amount, fee, tokenExportNonce[msg.sender]));
bytes32 _message = keccak256(abi.encodePacked(_prefix, _messageNoPrefix));
address _recover = ecrecover(_message, _v, _r, _s);
require(_recover == verifier, "verification failed");
tokenExportNonce[msg.sender]++;
address accountHodler = accountHodlerOf(msg.sender);
if (address(accountHodler).codehash == 0) {
require(deploy(accountHodler, msg.sender), "Failed to deploy the contract");
AccountHodler(accountHodler).initialize(owner);
}
AccountHodler(accountHodler).exportToken(token,msg.sender, feeReceiver, amount, fee);
}
SOLVED: The SeaScape team
now validates the inputs where an address is used to verify they are non-zero before performing any functionality.
Halborn used automated testing techniques to enhance the coverage of certain areas of the smart contracts in scope. Among the tools used was Slither, a Solidity static analysis framework. After Halborn verified the smart contracts in the repository and was able to compile them correctly into their abis and binary format, Slither was run against the contracts. This tool can statically verify mathematical relationships between Solidity variables to detect invalid or inconsistent usage of the contracts' APIs across the entire code-base.
Lord.sol and Mead.sol
No major issues found by Slither.
Halborn used automated security scanners to assist with detection of well-known security issues and to identify low-hanging fruits on the targets for this engagement. Among the tools used was MythX, a security analysis service for Ethereum smart contracts. MythX performed a scan on the smart contracts and sent the compiled results to the analyzers in order to locate any vulnerabilities.
Lord.sol
Mead.sol
No major issues found by MythX.
Halborn strongly recommends conducting a follow-up assessment of the project either within six months or immediately following any material changes to the codebase, whichever comes first. This approach is crucial for maintaining the project’s integrity and addressing potential vulnerabilities introduced by code modifications.
// Download the full report
* Use Google Chrome for best results
** Check "Background Graphics" in the print settings if needed