TGViewer
Из Solidity в AI и дальше Из Solidity в AI и дальше @solidityset · 2.49K subscribers
Post #1484 601
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;


import "openzeppelin-contracts/contracts/access/Ownable.sol";
contract RewardSystem is Ownable {
mapping(address => uint256) public rewards;
mapping(address => uint256) public nonces;


constructor() Ownable(msg.sender) {}


// For PoC simplicity, we don't use real signatures
function claimReward(address user, uint256 amount, uint256 nonce, bytes memory signature) external {
require(rewards[user] >= amount, "Insufficient reward balance");
require(nonces[user] == nonce, "Invalid nonce");


// Vulnerability: Signature can be replayed once contract has funds
bytes32 messageHash = keccak256(abi.encode(
user,
amount,
nonce
));


// For PoC, use a simple signature check
bytes32 signedHash = abi.decode(signature, (bytes32));
require(signedHash == messageHash, "Invalid signature");


// Attempt to transfer reward
rewards[user] -= amount;
(bool success,) = msg.sender.call{value: amount}("");


// Vulnerability: Nonce is only incremented if transfer succeeds
if (success) {
nonces[user]++;
} else {
revert("Transfer failed");
}
}


// Helper function to add rewards - only owner can call
function addReward(address user, uint256 amount) external onlyOwner {
rewards[user] += amount;
}


// Helper function to receive ETH
receive() external payable {}
}


Функция claimReward увеличивает значение nonce пользователя только в случае успешного перевода ETH. Если в контракте нет ETH, msg.sender.call завершится с ошибкой, транзакция будет отменена, а значение nonces[user] не будет увеличено. Подпись пользователя, которая была действительна для этого значения nonce, остается действительной.

Злоумышленник может отслеживать эти неудачные заявки. Как только контракт RewardSystem будет профинансирован, злоумышленник может повторить исходную транзакцию пользователя, направив вознаграждение на свой собственный адрес.

Как исправить
: используйте nonce в каждом пути выполнения!

Убедитесь, что nonce используется (помечается как использованный) в каждом пути выполнения, независимо от того, завершилось ли оно успешно или неудачно. Лучшая практика заключается в том, чтобы использовать nonce сразу после его проверки и убедиться, что транзакция не будет отменена после этого момента. Таким образом, даже если транзакция завершится неудачно, nonce все равно будет увеличен, что предотвратит атаки повторного воспроизведения.

// Corrected claimReward function (inside RewardSystem)
function claimReward(address user, uint256 amount, uint256 nonce, bytes memory signature) external {
require(rewards[user] >= amount, "Insufficient reward balance");
require(nonces[user] == nonce, "Invalid nonce");


// For PoC, use a simple signature check
bytes32 messageHash = keccak256(abi.encode(user, amount, nonce));
bytes32 signedHash = abi.decode(signature, (bytes32));
require(signedHash == messageHash, "Invalid signature");


// REMEDIATION 1: Consume nonce right after validating it
nonces[user]++;


rewards[user] -= amount;
(bool success,) = msg.sender.call{value: amount}("");


if (!success) {
// Revert the reward deduction if transfer failed
rewards[user] += amount;
}
// REMEDIATION 2: No revert to ensure nonce is consumed
}


С этим исправлением, даже если передача не удалась, nonce становится недействительным. Злоумышленник не может повторно использовать подпись, поскольку контракт теперь будет ожидать nonce + 1.

#replay
  • 👍 2
  • 🔥 1
More from @solidityset
  1. Sep 22, 2026Какой язык программирования учить сейчас? На днях в Твиттере увидел небольшой пост о разви…
  2. Sep 18, 2026Интересная модель Jev Буквально пару дней назад в Твиттере многие начали обсуждение новой…
  3. Sep 14, 2026Графы повсюду Если вы также следите за новостями в мире ИИ, то наверняка уже все чаще встр…
  4. Sep 10, 2026GTA6, Cyberleek, блокчейн и безопасность Увидел несколько постов (тут и тут) про Cyberleek…
  5. Sep 9, 2026Работа с чистой энергией Дисклеймер Сегодня ава и название канала, наконец, поменялись. Я…
  6. Sep 9, 2026Channel name was changed to «Из Solidity в AI и дальше»
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →