Loading...
Loading...
Create production grade smart contracts. Use this skill when the user asks to write smart contracts, specially if they are going to be deployed to production (to a mainnet, or used in a mainnet script).
npx skill4agent add cyfrin/solskill solskill..// good
import {MyContract} from "contracts/MyContract.sol";
// bad
import "../MyContract.sol";revertrequireerror ContractName__MyError();
// Good
myBool = true;
if (myBool) {
revert ContractName__MyError();
}
// bad
require(myBool, "MyError");// good - using foundry's built in stateless fuzzer
function testMyTest(uint256 randomNumber) { }
// bad
function testMyTest() {
uint256 randomNumber = 0;
}constructor
receive function (if exists)
fallback function (if exists)
user-facing state-changing functions
(external or public, not view or pure)
user-facing read-only functions
(external or public, view or pure)
internal state-changing functions
(internal or private, not view or pure)
internal read-only functions
(internal or private, view or pure) /*//////////////////////////////////////////////////////////////
INTERNAL STATE-CHANGING FUNCTIONS
//////////////////////////////////////////////////////////////*/Pragma statements
Import statements
Events
Errors
Interfaces
Libraries
ContractsType declarations
State variables
Events
Errors
Modifiers
Functions.tree├── when the id references a null stream
│ └── it should revert
└── when the id does not reference a null stream
├── given assets have been fully withdrawn
│ └── it should return DEPLETED
└── given assets have not been fully withdrawn
├── given the stream has been canceled
│ └── it should return CANCELED
└── given the stream has not been canceled
├── given the start time is in the future
│ └── it should return PENDING
└── given the start time is not in the future
├── given the refundable amount is zero
│ └── it should return SETTLED
└── given the refundable amount is not zero
└── it should return STREAMINGfunction test_RevertWhen_Null() external {
uint256 nullStreamId = 1729;
vm.expectRevert(abi.encodeWithSelector(Errors.SablierV2Lockup_Null.selector, nullStreamId));
lockup.statusOf(nullStreamId);
}
modifier whenNotNull() {
defaultStreamId = createDefaultStream();
_;
}
function test_StatusOf()
external
whenNotNull
givenAssetsNotFullyWithdrawn
givenStreamNotCanceled
givenStartTimeNotInFuture
givenRefundableAmountNotZero
{
LockupLinear.Status actualStatus = lockup.statusOf(defaultStreamId);
LockupLinear.Status expectedStatus = LockupLinear.Status.STREAMING;
assertEq(actualStatus, expectedStatus);
}/**
* @custom:security-contact mycontact@example.com
* @custom:security-contact see https://mysite.com/ipfs-hash
*/ onlyOwner// good
uint256 x;
bool y;
// bad
uint256 x = 0;
bool y = false;// good
function getBalance() external view returns (uint256 balance) {
balance = balances[msg.sender];
}
// bad
function getBalance() external view returns (uint256) {
uint256 balance = balances[msg.sender];
return balance;
}calldatamemorycalldata// good — calldata length is cheap to read
for (uint256 i; i < items.length; ++i) { }
// bad — unnecessary caching for calldata
uint256 len = items.length;
for (uint256 i; i < len; ++i) { }msg.senderowneronlyOwnerSafeTransferLib::safeTransferETHcall()nonReentrantReentrancyGuardTransientnonReentrantOwnable2StepOwnableimmutablefoundry.tomlforge script// good - fork test verifying governance proposal outcome
function testGovernanceProposal_UpdatesPriceFeed() public {
vm.createSelectFork(vm.envString("MAINNET_RPC_URL"));
// Execute the governance proposal
_executeProposal(proposalId);
// Verify expected state after proposal
address newFeed = oracle.priceFeed(market);
assertEq(newFeed, EXPECTED_CHAINLINK_FEED);
// Verify the feed returns sane values
(, int256 price,,,) = AggregatorV3Interface(newFeed).latestRoundData();
assertGt(price, 0);
}solhintforge build --sizesslitheraderyn