Доклад Александра Мазалецкого на первой встрече сообщества блокчейн-разработчиков SPb BlockChain Community
https://www.facebook.com/spblockchain
1 of 18
Download to read offline
More Related Content
Надежные смарт контракты #spblockchain
1. Методики построения и архитектура
надежных смарт-контрактов
Александр Мазалецкий,
Dicoiner, inc
2. Рассмотрим на примере ERC-20 токенов и ICO
• Стандарт ERC-20: разработан в конце 2015 года, де-факто стандарт
для финансовых активов
• Многие предприятия решили собрать инвестиции посредством Initial
Coin Offering (ICO)
• In 2016, 64 ICOs собрали более 103 млн $ (CoinDesk)
3. Рассмотрим, например ERC-20 стандарт
Функция Описание
totalSupply() Общение количество токенов в обращении
balanceOf(A) Количество токенов принадлежащих A
transfer(A,x) Отправить количество токенов x стороне A
transferFrom(A,x) Списать количество токенов x со стороны A
approve(A,x) Подтвердить, что сторона A может списать токены
x от моего имени
allowance(A,B) Количество токенов, разрешенных стороне B на
вывод от лица стороны A
4. Безопасность
• Безопасность процесса ICO и надежность
контрактов является жизненно-важной
проблемой
• Угрозы:
• Потеря токенов из-за неправильного
поведения контракта
• Потеря доступности, другие контракты не
мог взаимодействовать с токеном из-за
ошибок
• Типовые уязвимости
• Небезопасный код
• Интерфейс с ошибками
6. Исключения в Solidity
• C1.F () не может перехватывать исключения
• C1.call () не может получить возвращаемые значения
• Исключения должны быть для исключительных событий!
function F(uint x)
returns uint{
If(x>42) throw;
else return 3}
X=C1.F(10);
….
X = C1.call(…”F”…)
C2 C1
7. Исключения вместо возвращаемого значения функции
Пример кода:
function transferFrom(address _from, address _to, uint _value) returns (bool
success) {
var _allowance = allowed[_from][msg.sender];
balances[_to] = safeAdd(balances[_to], _value);
balances[_from] = safeSub(balances[_from], _value); 1
allowed[_from][msg.sender] = safeSub(_allowance, _value);
Transfer(_from, _to, _value);
return true;
}
function safeSub(uint a, uint b) internal returns (uint) {
assert(b <= a);
return a - b;
}
8. Исключения вместо возвращаемого значения функции
• Пример кода:
• function transferFrom(address _from, address _to, uint _value) returns (bool
success) {
var _allowance = allowed[_from][msg.sender];
balances[_to] = safeAdd(balances[_to], _value);
balances[_from] = safeSub(balances[_from], _value);
allowed[_from][msg.sender] = safeSub(_allowance, _value);
Transfer(_from, _to, _value);
return true;
}
• Если баланса _from (отправителя) недостаточно или слишком маленькое значение
для допустимых токенов, генерируется исключение (а должно быть false).
9. Опираясь на выше сказанное
• function transferFrom(address _from, address _to, uint _value)
returns (bool success) {
var _allowance = allowed[_from][msg.sender];
balances[_to] = safeAdd(balances[_to], _value);
balances[_from] = safeSub(balances[_from], _value);
allowed[_from][msg.sender] = safeSub(_allowance, _value);
Transfer(_from, _to, _value);
return true;
}
• Значение баланса отправителя_to всегда будет расти
• Необходимо, предусмотреть, чтобы в случае понижения значение
allowance возвращалось исключение
10. Переполнение в SafeMath
• function safeMul(uint a, uint b) internal returns (uint) {
uint c = a * b;
assert(a == 0 || c / a == b);
return c;
}
• Код полагается на недокументированное поведение в Solidity
• Сначала идет создание переполнения, а зачем попытка обнаружить
• Переполнение может вести себя по разному, в итоге может привести к полной потере
токенов
• И все теже проблемы что были с SafeAdd
11. Кейс 2: the Approve() функция
Ломаем ERC-20 standard
12. Ситуация
1. Алиса разрешает перевести Бобу N-токенов
2. Затем Алиса решила изменить количество доступных токенов Бобу
для перевода и разрешает перевести M-токенов
3. Боб замечает последнюю транзакцию, до того как она была
подтверждена, и отправляет их Кэрол
4. После того как все транзакции Алиса подтверждены, Боб отправляет
Алиса еще N-токенов, в итоге переводит Кэрол, M+N токенов
5. Действия Боба не регистрируются нужным образом, событие transfer
знает только адреса Алиса и Кэрол
6. И еще больше проблем будет, если Алиса разрешила и Кэрол
переводить некоторое количество токенов
13. Предложение: генерация новых событий
1) function approve( address _spender, uint256
_currentValue, uint256 _value) returns (bool success)
Если значение разрешенное для _spender равно _currentValue, то
переписываем _value и возвращаем значение true, иначе false.
2) event Transfer( address indexed _spender, address
indexed _from, address indexed _to, uint256 _value)
3) event Approval( address indexed _owner, address
indexed _spender, uint256 _oldValue, uint256 _value)
15. Четкие требования и понимание поведения
• Определите функциональные требования для контракта и API
• Описывайте все возможные модели поведения!!!
• Следуйте четко базовым принципам безопасности