Мы разрабатываем смарт-контракты голландского аукциона для справедливого распределения токенов. Классический токен-сейл с фиксированной ценой создаёт одну из двух проблем: либо цена слишком низкая — все токены уходят в первые секунды (газовая война, несправедливое распределение в пользу MEV-ботов), либо слишком высокая — сейл не заполняется. Голландский аукцион решает обе проблемы за счёт динамического ценообразования: цена начинается высокой и снижается до тех пор, пока спрос не встретит предложение. Цена сейла — это рыночный клиринговый уровень, а не произвольное число из whitepaper. Именно так Paradigm и a16z проводили первые крупные токен-дистрибьюции в DeFi-пространстве. Gnosis Protocol использует вариацию этого механизма для batch аукционов. Наш опыт — 5 лет на рынке и более 30 успешных контрактов. Закажите разработку под ключ — мы сопровождаем проект от идеи до деплоя и аудита.
Почему экспоненциальное снижение цены эффективнее линейного? — разработка системы голландского
Простейшая реализация — линейная функция:
price(t) = startPrice - (startPrice - endPrice) * (t - startTime) / duration Проблема линейной модели: большую часть времени цена снижается медленно из-за равномерности. Участники ждут минимума, аукцион не заполняется в середине, все пытаются купить в конце. Экспоненциальное снижение более реалистично описывает рыночное поведение:
function getCurrentPrice() public view returns (uint256) { if (block.timestamp <= startTime) return startPrice; if (block.timestamp >= endTime) return endPrice; uint256 elapsed = block.timestamp - startTime; uint256 duration = endTime - startTime; // Экспоненциальное снижение через 18-decimal fixed point uint256 priceDelta = startPrice - endPrice; uint256 decayFactor = PRBMath.exp(-int256(decayRate * elapsed / duration)); return endPrice + priceDelta * decayFactor / 1e18; } На практике большинство production Dutch Auction контрактов используют дискретные шаги снижения (step-down) вместо непрерывной функции — это проще для понимания участниками и дешевле в газе.
| Характеристика | Линейное снижение | Экспоненциальное снижение |
|---|---|---|
| Скорость падения в начале | Медленная | Быстрая |
| Привлекательность для ранних участников | Низкая | Высокая |
| Риск незаполнения | Высокий | Низкий |
| Сложность реализации | Простая | Средняя |
| Газовые затраты | Низкие | Умеренные |
Как защититься от MEV в Dutch Auction?
В стандартном Dutch Auction все видят текущую цену, и как только она становится "справедливой", все пытаются купить одновременно. MEV-боты front-run реальных покупателей, выставляя более высокий gas price. Результат: газовая война, но уже при клиринговой цене вместо стартовой. Решение — commit-reveal: участники отправляют encrypted commitment (hash от суммы и salt) без раскрытия намерения. После завершения фазы commitment — reveal фаза. Клиринговая цена рассчитывается по совокупному спросу. Это сложнее в реализации, но устраняет front-running полностью. GnosisDAO использовал подобную схему для своих аукционов.
Ключевые контрактные параметры
struct AuctionConfig { uint256 startPrice; // Максимальная цена (например, 1 ETH за токен) uint256 endPrice; // Минимальная цена (например, 0.1 ETH) uint256 startTime; // Unix timestamp начала uint256 endTime; // Unix timestamp конца uint256 totalTokens; // Количество токенов на продажу uint256 minBidAmount; // Минимальная покупка bool allowWhitelist; // Ограничить до whitelist bytes32 merkleRoot; // Merkle root для whitelist } Whitelist через Merkle Proof
Если аукцион ограничен для определённых адресов:
function bid(uint256 amount, bytes32[] calldata merkleProof) external payable { if (config.allowWhitelist) { bytes32 leaf = keccak256(abi.encodePacked(msg.sender)); require( MerkleProof.verify(merkleProof, config.merkleRoot, leaf), "Not whitelisted" ); } uint256 currentPrice = getCurrentPrice(); uint256 tokenAmount = msg.value * 1e18 / currentPrice; require(tokenAmount >= config.minBidAmount, "Below minimum"); require(tokensSold + tokenAmount <= config.totalTokens, "Exceeds supply"); tokensSold += tokenAmount; bids[msg.sender] += tokenAmount; emit BidPlaced(msg.sender, tokenAmount, currentPrice, msg.value); } Возврат переплаты: клиринговая цена
В классическом Dutch Auction участники платят цену момента покупки. В Fair Dutch Auction (DutchX, Gnosis) — все платят одну клиринговую цену, даже те, кто купил раньше по более высокой. Разница возвращается. Это справедливее, но сложнее в реализации: нужно дождаться конца аукциона, рассчитать клиринговую цену, и дать каждому участнику забрать refund через отдельный claim.
function claim() external { require(auctionEnded, "Auction not ended"); uint256 userBid = bids[msg.sender]; require(userBid > 0, "No bid"); uint256 paid = payments[msg.sender]; uint256 cost = userBid * clearingPrice / 1e18; uint256 refund = paid - cost; bids[msg.sender] = 0; payments[msg.sender] = 0; // Переводим токены token.transfer(msg.sender, userBid); // Возвращаем переплату if (refund > 0) { (bool success, ) = msg.sender.call{value: refund}(""); require(success, "Refund failed"); } } Типичные ошибки и уязвимости
Ошибки расчёта клиринговой цены. Если tokensSold не достиг totalTokens — аукцион закрылся по endPrice. Если достиг раньше — клиринговая цена это цена момента заполнения. Контракт должен корректно обрабатывать оба сценария, иначе либо пользователи не получат refund, либо контракт отдаст больше токенов, чем должен.
Округление в пользу контракта. При делении wei на цену возникают remainder. Всегда округляем количество токенов вниз, сохраняем dust как treasury или включаем в burn-механизм.
Reentrancy в claim(). ETH-refund перед или вместе с transfer токенов — классическая точка reentrancy. Обновляем bids[msg.sender] = 0 до любых внешних вызовов.
Отсутствие паузы. Если обнаружена ошибка во время аукциона — нужна экстренная остановка. Функция pause() с multisig-контролем, которая замораживает новые bids, но не блокирует claim для уже сделанных.
Что входит в разработку
- Смарт-контракт Dutch Auction с поддержкой линейного или экспоненциального снижения
- Механизм commit-reveal для защиты от MEV (опционально)
- Клиринговая цена с возвратом переплаты через claim
- Whitelist на основе Merkle Tree
- Полный набор тестов на Forge + статический анализ Slither
- Аудит безопасности (внутренний + внешний по желанию)
- Документация и инструкция по деплою
- Поддержка после деплоя (2 недели)
Сроки разработки: 3-5 рабочих дней для базового Dutch Auction, до 2 недель для Fair Dutch Auction с commit-reveal. Стоимость рассчитывается индивидуально. Получите консультацию — оценим ваш проект за 1 день.
Почему выбирают нас
- 5 лет опыта в разработке смарт-контрактов на Solidity и Rust
- Более 30 успешных проектов в DeFi (гарантия качества)
- Используем современные инструменты: Foundry, Tenderly, OpenZeppelin
- Предоставляем сертификаты аудита и формальной верификации по запросу
Свяжитесь с нами, чтобы обсудить ваш проект. Мы подберём оптимальную архитектуру аукциона под ваши требования.







