Немного подробнее.
Если атакующий делает проигрышную ставку с контракта, а в контракте есть receive, которая всегда возвращает ошибку, то попытки возместить проигравшую ставку заведомо обречены. В коде возврат делался стандартным образом:
А коль скоро возвратов много и их надо обрабатывать в цикле, то как только попадается адрес контракта злоумышленника, то и вся цепочка обрывается. Правда потом злоумышленник всё-таки вышел на связь и сказал, что просто хотел показать ненадёжность аукциона и этот блок убрал (у него в receive просто стояло элементарное условие вида "возвращать ошибку/не возвращать ошибку"). Если ошибку не возвращать, то просто пробрасывать принятые деньги на кошелёк атакующего, что вернуть свою ставку. Ну, либо там мог быть бесконечный цикл, вот пример https://twitter.com/0xInuarashi/status/1517677597978599425
Вроде бы, всё ок, то есть возвраты стали работать и участники аукциона свои деньги назад таки получили.
Но есть и другой неприятный момент. В коде для функции
Однако дополнительно была введена переменная
А дальше самое интересное. В функции для обработки возвратов стояло ещё одно условие
Фактически, это условие истинным не будет никогда, то есть устроители аукциона обманули самих себя, и деньги застряли на их же контракте.
Если атакующий делает проигрышную ставку с контракта, а в контракте есть receive, которая всегда возвращает ошибку, то попытки возместить проигравшую ставку заведомо обречены. В коде возврат делался стандартным образом:
if (refund > 0) {
(bool sent, ) = bidData.bidder.call{value: refund}("");
require(sent, "Failed to refund bidder");
}А коль скоро возвратов много и их надо обрабатывать в цикле, то как только попадается адрес контракта злоумышленника, то и вся цепочка обрывается. Правда потом злоумышленник всё-таки вышел на связь и сказал, что просто хотел показать ненадёжность аукциона и этот блок убрал (у него в receive просто стояло элементарное условие вида "возвращать ошибку/не возвращать ошибку"). Если ошибку не возвращать, то просто пробрасывать принятые деньги на кошелёк атакующего, что вернуть свою ставку. Ну, либо там мог быть бесконечный цикл, вот пример https://twitter.com/0xInuarashi/status/1517677597978599425
Вроде бы, всё ок, то есть возвраты стали работать и участники аукциона свои деньги назад таки получили.
Но есть и другой неприятный момент. В коде для функции
claimProjectFunds, которая выводила деньги на счёт устроителей, было условие refundProgress >= totalBids (то есть нужно, чтобы было выплачено возвратов столько, сколько было ставок, видимо) - только после этого сами владельцы контракта могут забрать вырученные средства, то есть победившие ставки.Однако дополнительно была введена переменная
bidIndex, которая тоже была связана с числом ставок. В функцию bid, приходила не только денежная сумма, а ещё и количество ставок (amount), которое могло варьироваться от 1 до 3. Но владельцы контракта это не учли и вместо того, чтобы написать bidIndex += amount написали bidIndex++ (ну, либо им надо было ещё одну переменную выделять на это).А дальше самое интересное. В функции для обработки возвратов стояло ещё одно условие
require(_refundProgress < _bidIndex, "Refunds already processed");. То есть кол-во возвратов не могло превышать кол-во bidIndex. Но если вспомнить, что bidIndex считается неправильно (а многие юзеры делали сразу много ставок), то refundProgress всегда будет меньше, чем totalBids (то есть кол-во ставок в принципе, которое как раз считалось правильно). А теперь мы вспомним условие в функции "забрать себе деньги за аукцион": require(refundProgress >= totalBids, "Refunds not yet processed");.Фактически, это условие истинным не будет никогда, то есть устроители аукциона обманули самих себя, и деньги застряли на их же контракте.
Twitter
0xInuarashi
7/ As for a solidity readable, it was probably something similar to this. If block, fail the receivable fallback. Otherwise, let it succeed. Demonstration was written by @notchefbob which tried to notify the team of the issue.
👍9🔥4
В этом уроке мы закончим интерфейс для нашего аукциона, добавим динамическое обновление цены, сделаем кнопку для покупки и подпишемся на события. https://youtu.be/13YY-YQoG60
YouTube
Solidity и смарт-контракты Ethereum, урок #15 | Фронт-энд на Next.js, часть 2
ХОТИТЕ СТАТЬ РАЗРАБОТЧИКОМ Solidity, узнать об Ethereum, блокчейне и многом другом ещё больше?!
Мои друзья из GUIDE DAO (бывшая школа MCS) предлагают скидку 0,1 ETH на ВСЕ СВОИ БУТКЕМЫ ПО КРИПТЕ! Материалы этих буткемов подготовлены мной и другими специалистами:…
Мои друзья из GUIDE DAO (бывшая школа MCS) предлагают скидку 0,1 ETH на ВСЕ СВОИ БУТКЕМЫ ПО КРИПТЕ! Материалы этих буткемов подготовлены мной и другими специалистами:…
🔥11👍6
Я всё ещё эпизодами дочитываю в очередной раз Тэффи и нашёл такой момент:
Интересно, как у разных людей разнятся мысли. Я никогда не привязывался ни к вещам, ни к месту (хотя, конечно, у Тэффи "казалось бы" - тоже намёк на то, что не всё так просто).
Когда-то, в другой жизни, я уехал практически без ничего. Сумка с компьютером, который спустя год всё равно пришлось собирать заново посреди ночи из тех запчастей, что удалось купить в срочном порядке, сумка с кошкой, стойка и микрофон, какой-то минимум одежды...
А потом как-то обживаешься, и в общем-то не скучаешь по тому, что осталось где-то там, от чего и так уже в душе давным-давно отказался. То же самое можно купить опять, это ведь не проблема. Вещей не жаль. Жаль людей.
И тут вспоминается Сапковский:
Действительно жаль. Когда теперь ещё увидимся?
Но остаётся работа, остаются мысли о том, что, насколько это возможно, мы можем делать мир лучше - хотя бы для кого-то. Отзывы зрителей - это лучшая награда.
А теперь почему-то вспоминается давнее турне по Италии и Франции, которое удалось устроить лет... хотел написать 5-6, но, кажется, уже 6-7 назад.
Тогда мы как раз и посетили Русское кладбище в пригороде Парижа, поклонились могиле Тэффи, Нуреева, участникам белого движения... К счастью, родственники помогли обустроиться, так что мы прожили во Франции почти неделю.
В один день зашли в какой-то бар и почему-то @ailura24 улетела с одного коктейля (алкоголя налили много?). Ходили по всему Версалю как два шатающихся дурака. Глупо ведь, а весело. Потом уже ночью гуляли все вместе, какие-то весёлые парижане кричали нам с балкона, приглашали на тусовку к ним домой.
Причём ведь сейчас тоже можно повторить что-то подобное, даже гораздо проще, но как-то душа не лежит. Тяжело. Хочется быть эдаким рубаха-парнем, а выходит мужик неопределённого возраста, который наговаривает заранее неотрепетированный текст в микрофон (впрочем, текст не репетировался никогда) скрипучим голосом, а два раза в неделю избивает грушу в зале. Да, и мучает студентов раз в неделю на семинарах. Впрочем, это ведь на пользу.
В любом случае, не нужно опускать руки. Мы живы, мы здесь. Adsumus. Adsumus in nomine tuo.
Портрет мой, нарисованный Репиным, получился какой-то волшебно-нежный, совсем неожиданный, не похожий на могучую лепку репинской кисти.
Он обещал его мне. Но ко мне он так и не попал. Был послан на выставку в Америку и, по словам Репина, застрял в таможне.
Мне неловко было расспрашивать и настаивать. Мне говорили:
— Он не хочет признаться, что продал его.
Все равно. Он пропал бы во время революции, как пропали все мои портреты и многие любимые мною вещи, без которых, казалось бы, и жить не стоило…
Интересно, как у разных людей разнятся мысли. Я никогда не привязывался ни к вещам, ни к месту (хотя, конечно, у Тэффи "казалось бы" - тоже намёк на то, что не всё так просто).
Когда-то, в другой жизни, я уехал практически без ничего. Сумка с компьютером, который спустя год всё равно пришлось собирать заново посреди ночи из тех запчастей, что удалось купить в срочном порядке, сумка с кошкой, стойка и микрофон, какой-то минимум одежды...
А потом как-то обживаешься, и в общем-то не скучаешь по тому, что осталось где-то там, от чего и так уже в душе давным-давно отказался. То же самое можно купить опять, это ведь не проблема. Вещей не жаль. Жаль людей.
И тут вспоминается Сапковский:
- Co ty mozesz wiedziec, Itka - miauknela cicho, zlowrogo kotka. - Zal? Moze i tak, zal mi ich. Zal mi dotyku ich rak. Zal mi szmeru ich oddechów, gdy spia. Zal mi ciepla ich kolan. Zal mi naszej muzyki, która, ledwo poznana, trace.
Действительно жаль. Когда теперь ещё увидимся?
Но остаётся работа, остаются мысли о том, что, насколько это возможно, мы можем делать мир лучше - хотя бы для кого-то. Отзывы зрителей - это лучшая награда.
А теперь почему-то вспоминается давнее турне по Италии и Франции, которое удалось устроить лет... хотел написать 5-6, но, кажется, уже 6-7 назад.
Тогда мы как раз и посетили Русское кладбище в пригороде Парижа, поклонились могиле Тэффи, Нуреева, участникам белого движения... К счастью, родственники помогли обустроиться, так что мы прожили во Франции почти неделю.
В один день зашли в какой-то бар и почему-то @ailura24 улетела с одного коктейля (алкоголя налили много?). Ходили по всему Версалю как два шатающихся дурака. Глупо ведь, а весело. Потом уже ночью гуляли все вместе, какие-то весёлые парижане кричали нам с балкона, приглашали на тусовку к ним домой.
Причём ведь сейчас тоже можно повторить что-то подобное, даже гораздо проще, но как-то душа не лежит. Тяжело. Хочется быть эдаким рубаха-парнем, а выходит мужик неопределённого возраста, который наговаривает заранее неотрепетированный текст в микрофон (впрочем, текст не репетировался никогда) скрипучим голосом, а два раза в неделю избивает грушу в зале. Да, и мучает студентов раз в неделю на семинарах. Впрочем, это ведь на пользу.
В любом случае, не нужно опускать руки. Мы живы, мы здесь. Adsumus. Adsumus in nomine tuo.
👍17🤔2👎1🤯1😢1
В этом видео мы начнём говорить о безопасности смарт-контрактов. Узнаем о том, что такое атаки типа Reentrancy и DoS (denial of service), как они реализуются и как от них защититься. https://www.youtube.com/watch?v=GVTZuuzCbIs
YouTube
Solidity и смарт-контракты Ethereum, урок #16 | Безопасность: Reentrancy, DoS
ХОТИТЕ СТАТЬ РАЗРАБОТЧИКОМ Solidity, узнать об Ethereum, блокчейне и многом другом ещё больше?!
Мои друзья из GUIDE DAO (бывшая школа MCS) предлагают скидку 0,1 ETH на ВСЕ СВОИ БУТКЕМЫ ПО КРИПТЕ! Материалы этих буткемов подготовлены мной и другими специалистами:…
Мои друзья из GUIDE DAO (бывшая школа MCS) предлагают скидку 0,1 ETH на ВСЕ СВОИ БУТКЕМЫ ПО КРИПТЕ! Материалы этих буткемов подготовлены мной и другими специалистами:…
🔥14👍3🤔1
https://faucet.paradigm.xyz/ - запрос денежных средств в разных тестовых сетях
faucet.paradigm.xyz
Paradigm MultiFaucet | Bootstrap your testnet wallet
MultiFaucet funds a wallet with ETH, wETH, DAI, and NFTs across 8 testnet networks, at once.
❤7
Друзья, возник справедливый вопрос по атаке типа reentrancy и функциям transfer/send - являются ли они гарантией безопасности?
Так вот, reentrancy в теории может быть везде, где есть вызов сторонних контрактов. Желательно априори считать вызов сторонних неизвестных контрактов небезопасным.
Функции transfer/send действительно имеют жёсткий лимит по газу (2300), но и в него тоже можно уместиться и сделать что-нибудь нехорошее. Вообще-то, раньше transfer действительно считалась безопасной функцией (её и ввели для защиты от reentrancy), но только никто не учёл, что стоимости по газу могут меняться. Если раньше "втиснуться" в лимит 2300 особо было нельзя, то теперь вполне можно (стоимости упали). Например, вот тут немного подробнее https://immunebytes.com/transfer-in-solidity-why-you-should-stop-using-it/ Короче, нужно быть осторожными
Так вот, reentrancy в теории может быть везде, где есть вызов сторонних контрактов. Желательно априори считать вызов сторонних неизвестных контрактов небезопасным.
Функции transfer/send действительно имеют жёсткий лимит по газу (2300), но и в него тоже можно уместиться и сделать что-нибудь нехорошее. Вообще-то, раньше transfer действительно считалась безопасной функцией (её и ввели для защиты от reentrancy), но только никто не учёл, что стоимости по газу могут меняться. Если раньше "втиснуться" в лимит 2300 особо было нельзя, то теперь вполне можно (стоимости упали). Например, вот тут немного подробнее https://immunebytes.com/transfer-in-solidity-why-you-should-stop-using-it/ Короче, нужно быть осторожными
👍12
Для "развлечения" сделал скрипт, который подбирает "красивые" адреса контрактов, которые разворачиваются через create2. То есть просто подбирается соль. Код нужно сильно оптимизировать, но всё же это работает:
function stringGen(len) {
var text = "";
var charset = "abcdefghijklmnopqrstuvwxyz0123456789";
for (var i = 0; i < len; i++)
text += charset.charAt(Math.floor(Math.random() * charset.length));
return text;
}
const func = async function (hre) {
const {deployments, getNamedAccounts} = hre;
const {deploy} = deployments;
const {deployer} = await getNamedAccounts();
while(true) {
let salt = stringGen(Math.floor(Math.random() * 30))
let res = await deploy('TestContract', {
from: deployer,
log: false,
deterministicDeployment: hre.ethers.utils.solidityKeccak256(["string"], [salt]),
});
if(res.address[2] === res.address[3] && res.address[2] === res.address[4] && res.address[2] === res.address[5]) {
console.log(res.address, salt)
break;
}
}
};
export default func;
К примеру, с солью u8phmitlg9hse17xin8 и небольшим демо-контрактом выходит адрес 0x88880b14BDFF750Ce5B58d1A55fCa65403BdBaaE (четыре восьмёрки в начале). Скрипт работает с помощью hardhat-deploy👍10🔥1😁1
Немного музыки на сегодня. Всем мира и спокойной ночи https://www.youtube.com/watch?v=7Mfa8VxO0sM
YouTube
2022 - SABATON - The War to End All Wars (Full album)
1. Stormtroopers 00:00
2. Dreadnought 03:56
3. The Unkillable Soldier 08:54
4. Soldier of Heaven 13:04
5. Hellfighters 16:42
6. Race to the Sea 20:09
7. Lady of the Dark 23:56
8. The Valley of Death 26:58
9. Christmas Truce 31:12
10. Versailles…
2. Dreadnought 03:56
3. The Unkillable Soldier 08:54
4. Soldier of Heaven 13:04
5. Hellfighters 16:42
6. Race to the Sea 20:09
7. Lady of the Dark 23:56
8. The Valley of Death 26:58
9. Christmas Truce 31:12
10. Versailles…
❤6
Новое издание книги по Rails и фронт-энду, в сентябре уже выйдет из беты https://pragprog.com/noscripts/nrclient2/modern-front-end-development-for-rails-second-edition/
Pragprog
Modern Front-End Development for Rails, Second Edition
Combine Rails 7, TypeScript, Turbo, Stimulus, and React to build rich user interaction into your websites using the best of both server and client-side tools.
👍5
"Hello world" на разных языках программирования (примеров сотни). Кстати, Solidity нет, поэтому желающие могут добавить 😄 http://helloworldcollection.de/
helloworldcollection.de
The Hello World Collection
The largest collection of Hello World programs on the Internet.
Немного музыки на сегодня. https://www.youtube.com/watch?v=ClSWxwwUYkw
YouTube
We Lost The Sea - A Gallant Gentleman - Live at Studios 301 (Official Video)
This is the first release off We Lost The Sea's latest album 'Departure Songs'. Recorded during live tracking of the album at Studios 301 in Sydney featuring the high school girls choir from Mercy College in Chatswood.
ALBUM NOW AVAILABLE VIA BANDCAMP. …
ALBUM NOW AVAILABLE VIA BANDCAMP. …
👍1
Любопытная мысль об ООП в целом:
А речь о том, что написание красивого и понятного кода - это искусство, а не ремесло. В некоторых видео (каюсь, в основном только про Ruby) я пытаюсь донести эту мысль. Нужно немного расширить границы и делать не так, как учили (тем более, что обычно вообще никого не "учили"), а как кажется правильным. Да, потом это может оказаться неправильным и неоптимальным, но всё можно переписать. Зато в один прекрасный день вы увидите, что не ЯЗЫК управляет ВАМИ, а ВЫ управляете ЯЗЫКОМ. В конце концов, для кого вообще создавались языки программирования? Уж точно не для железки, которая понимает только нолики и единички (ну, в отдельных случаях бывает ещё троичная логика, да).
Долгое время понять это довольно сложно, потому что выход за рамки приводит к постоянно ломающимся программам - у меня так тоже было довольно долгое время. Но потом - бац - и что-то перещёлкивает, и ты смотришь на это всё несколько иначе.
I really like the way Bruce Richardson put it:
nobody slicing bread thinks they’re sending a message telling the knife to cut the bread or telling the bread to be sliced
OOP is about putting some awkward constraints on the way that you are allowed to use your language. Perhaps in some cases it makes sense, but in most cases it doesn’t. If OOP is about tying some actions to some objects, then if someone wants to perform some action that wasn’t anticipated by the designer, they have a problem.
Therefore OOP forces you to come up with solutions to issues that appear solely because someone decided to use the constraints of OOP in your project, like “which class should this method belong to?” (“oh I know I should create a controller class”).
I believe the only approach that actually scales is trying to express your way of thinking about problem, rather than imposing some arbitrary and artificial constraints beforehand. Solving problems that could be avoided is just a waste of time.
А речь о том, что написание красивого и понятного кода - это искусство, а не ремесло. В некоторых видео (каюсь, в основном только про Ruby) я пытаюсь донести эту мысль. Нужно немного расширить границы и делать не так, как учили (тем более, что обычно вообще никого не "учили"), а как кажется правильным. Да, потом это может оказаться неправильным и неоптимальным, но всё можно переписать. Зато в один прекрасный день вы увидите, что не ЯЗЫК управляет ВАМИ, а ВЫ управляете ЯЗЫКОМ. В конце концов, для кого вообще создавались языки программирования? Уж точно не для железки, которая понимает только нолики и единички (ну, в отдельных случаях бывает ещё троичная логика, да).
Долгое время понять это довольно сложно, потому что выход за рамки приводит к постоянно ломающимся программам - у меня так тоже было довольно долгое время. Но потом - бац - и что-то перещёлкивает, и ты смотришь на это всё несколько иначе.
👍15🔥1
И последняя мысль на сегодня, но тут, скорее, просто заметка или памятка для себя. Связана эта мысль с тем, почему вообще я делаю то, что делаю (а вы это спрашивали уже несколько раз)? Ради чего? Ну, или почему я общаюсь с теми, с кем общаюсь? Можно ведь просто заниматься рабочими вопросами. А что - работа есть, задачи есть, а вечером можно расслабиться.
Ну, наверное, потому, что все эти люди, которые смотрят мои видео, не гонят меня прочь, не опускают глаза, отвечают мне, хотя далеко не всегда соглашаются с моей точкой зрения (это вовсе не значит, что на основной работе есть какие-то проблемы, речь тут о другом). Потому что я чувствую здесь себя "в теме". Как это глупо звучит, да?
Но ведь все мы родом из детства, а в детстве приходилось пережить много чего. Да и не в детстве тоже: вообще довольно сложно найти кого-то, кто тебя поймёт. Именно поэтому мне так нравится высказывание моего бывшего начальника: "Счастье - это когда тебя понимают и когда ты нужен".
Ну, наверное, потому, что все эти люди, которые смотрят мои видео, не гонят меня прочь, не опускают глаза, отвечают мне, хотя далеко не всегда соглашаются с моей точкой зрения (это вовсе не значит, что на основной работе есть какие-то проблемы, речь тут о другом). Потому что я чувствую здесь себя "в теме". Как это глупо звучит, да?
Но ведь все мы родом из детства, а в детстве приходилось пережить много чего. Да и не в детстве тоже: вообще довольно сложно найти кого-то, кто тебя поймёт. Именно поэтому мне так нравится высказывание моего бывшего начальника: "Счастье - это когда тебя понимают и когда ты нужен".
Jadę z nimi, bo jestem bezwolny golem. Bo jestem wiecheć pakuł gnany wiatrem wzdłuż gościńca. Dokąd, powiedz mi, mam pojechać? I po co? Tutaj przynajmniej zebrali się tacy, z którymi mam o czym rozmawiać. Tacy, którzy nie przerywają rozmowy, gdy podchodzę. Tacy, którzy nawet nie lubiąc mnie, mówią mi to w oczy, nie rzucają kamieniami zza opłotków. Jadę z nimi z tego samego powodu, dla którego pojechałem z tobą do flisackiej oberży. Bo jest mi wszystko jedno. Nie mam miejsca, do którego mógłbym zmierzać. Nie mam celu, który powinien znajdować się na końcu drogi.
👍16❤5
В этом уроке мы поговорим о низкоуровневых вызовах call и delegatecall, узнаем, в чём их отличие, как работать с возвращаемыми ими данными. Посмотрим, как работать с encodeWithSignature и encodeWithSelector, а также узнаем, к каким проблемам безопасности может привести использование delegatecall. https://www.youtube.com/watch?v=QzdMZbcn3o4
YouTube
Solidity и смарт-контракты Ethereum, урок #17 | Низкоуровненые вызовы и безопасность
ХОТИТЕ СТАТЬ РАЗРАБОТЧИКОМ Solidity, узнать об Ethereum, блокчейне и многом другом ещё больше?!
Мои друзья из GUIDE DAO (бывшая школа MCS) предлагают скидку 0,1 ETH на ВСЕ СВОИ БУТКЕМЫ ПО КРИПТЕ! Материалы этих буткемов подготовлены мной и другими специалистами:…
Мои друзья из GUIDE DAO (бывшая школа MCS) предлагают скидку 0,1 ETH на ВСЕ СВОИ БУТКЕМЫ ПО КРИПТЕ! Материалы этих буткемов подготовлены мной и другими специалистами:…
👍20
Говорят, с апдейтом Hardhat и glob какие-то проблемы (не проверял ещё)
Forwarded from Roman Brix
I finally found it.
glob@7.2.2 <- This is problem
I haven't looked for it exactly from what point, but it's version 7.2.0 in the package at the point where that package works well, and version 7.2.2 in the "nothing to compile" version.
Type the "npm intstall glob@7.2.0" into an empty project and copy /node_modules/glob
copy /node_modules/glob to YOUR_HARDHAT_PROJECT/node_modules/hardhat/node_modules/glob
It works.
glob@7.2.2 <- This is problem
I haven't looked for it exactly from what point, but it's version 7.2.0 in the package at the point where that package works well, and version 7.2.2 in the "nothing to compile" version.
Type the "npm intstall glob@7.2.0" into an empty project and copy /node_modules/glob
copy /node_modules/glob to YOUR_HARDHAT_PROJECT/node_modules/hardhat/node_modules/glob
It works.
Срочно в номер: оказывается, в Remix можно выбрать одну из нескольких тем оформления. Правда Old Hope нет :( https://remix-ide.readthedocs.io/en/latest/layout.html#themes
👍2