Security is paramount when building blockchain applications. This guide covers essential security practices for smart contract development on Paxeer Network.
Security is critical. A single vulnerability can lead to permanent loss of funds. Always prioritize security over speed of development.
Always use well-tested, audited libraries like OpenZeppelin:
Copy
// ✅ Good: Use OpenZeppelinimport "@openzeppelin/contracts/token/ERC20/ERC20.sol";import "@openzeppelin/contracts/access/Ownable.sol";contract MyToken is ERC20, Ownable { constructor() ERC20("MyToken", "MTK") Ownable(msg.sender) {}}// ❌ Bad: Roll your own implementationcontract MyToken { mapping(address => uint256) public balances; // Custom implementation may have bugs}
Implement proper access control for sensitive functions:
Ownable
AccessControl
Custom Modifiers
Copy
import "@openzeppelin/contracts/access/Ownable.sol";contract MyContract is Ownable { constructor() Ownable(msg.sender) {} function adminFunction() external onlyOwner { // Only owner can call } function transferOwnership(address newOwner) public override onlyOwner { // Transfer ownership safely super.transferOwnership(newOwner); }}
Copy
import "@openzeppelin/contracts/access/AccessControl.sol";contract MyContract is AccessControl { bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE"); bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); constructor() { _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); _grantRole(ADMIN_ROLE, msg.sender); } function adminFunction() external onlyRole(ADMIN_ROLE) { // Only admins can call } function mint(address to, uint256 amount) external onlyRole(MINTER_ROLE) { // Only minters can call }}
contract SafeMath { function add(uint256 a, uint256 b) public pure returns (uint256) { // ✅ Automatically reverts on overflow in 0.8+ return a + b; } function unsafeAdd(uint256 a, uint256 b) public pure returns (uint256) { // ❌ Can overflow - only use when certain it's safe unchecked { return a + b; } }}
Only use unchecked blocks when you’re absolutely certain overflow is impossible, like incrementing a loop counter.
// Look for:- .call()- .delegatecall()- .transfer()- .send()- External contract calls// Ask:- Can this reenter?- Is the recipient trusted?- Is the return value checked?- Is state updated before the call?
Check Access Control
Verify all privileged functions:
Copy
// Questions to ask:- Who can call this function?- Is there a modifier protecting it?- Can ownership be renounced?- Are there emergency controls?- Is multi-sig recommended?
Review State Changes
Analyze all state modifications:
Copy
// Check:- Are balances updated correctly?- Can state become inconsistent?- Are events emitted for changes?- Is data properly indexed?
Validate Math Operations
Review arithmetic:
Copy
// Verify:- No overflow/underflow (unless unchecked)- Division by zero protection- Rounding handled correctly- Precision loss considered
// Use OpenZeppelin's upgradeable contractsimport "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";contract MyTokenUpgradeable is Initializable, ERC20Upgradeable, OwnableUpgradeable{ function initialize() public initializer { __ERC20_init("MyToken", "MTK"); __Ownable_init(msg.sender); }}
Copy
// Use Gnosis Safe for critical operations// Deploy multi-sig wallet// Transfer ownership to multi-sigcontract MyContract is Ownable { constructor(address multiSig) Ownable(multiSig) {} // All admin functions require multi-sig approval}
contract InvariantTest is Test { MyContract contract; function setUp() public { contract = new MyContract(); } // Total supply should never change function invariant_totalSupply() public { assertEq( contract.totalSupply(), INITIAL_SUPPLY ); } // Balance sum should equal total supply function invariant_balanceSum() public { uint256 sum = 0; address[] memory users = contract.getUsers(); for (uint i = 0; i < users.length; i++) { sum += contract.balanceOf(users[i]); } assertEq(sum, contract.totalSupply()); }}
# Bug Bounty Program## Rewards- Critical: $10,000 - $50,000- High: $5,000 - $10,000- Medium: $1,000 - $5,000- Low: $100 - $1,000## Scope- All smart contracts at [addresses]- Vulnerabilities that lead to loss of funds- Access control bypasses- Economic attacks## Out of Scope- Known issues- Gas optimizations- UI/UX issues## ReportingSubmit to [email protected]