Features
- A decentralized URL shortening service built on Base
- Create, update and delete your own short links with auto-generated codes by default, or custom codes (premium feature)
- Will create a short URL like vado.link/5XdE0i or a custom one like vado.link/custom (premium feature)
- Multiple access methods, ranging from centralized to fully decentralized
- Analytics for each link (premium feature)
Fees
All fees are defined within the contracts, and are automatically applied when creating a link. Additionally, general access to the app and premium features require holding a certain amount of $VADO.
All fees and thresholds can be changed by the owner of the vado contract.
Type | Amount |
---|---|
Base fee | 0.001 Ξ per link creation |
Discounted fee | 0.0001 Ξ per link creation if you hold amount of $VADO required for premium features |
100 $VADO required in wallet to be able to create links | |
5000 $VADO required in wallet for premium features |
Architecture
vado contracts
Contract | Description |
---|---|
Vado.sol | Main contract handling deployment and upgradeability. Inherits from all abstract contracts below: |
VadoLinks.sol | All link management logic and composition of other contract abstracts |
VadoAccess.sol | Access control mechanism for link creation |
VadoFees.sol | Fee management for link creation |
VadoPremium.sol | Premium mechanism and modifier |
VadoRandomizer.sol | Helpers for generating link codes |
VadoToken.sol | ERC20 utility token used as access token and premium features |
All contracts are deployed on Base with proxy (UUPS upgradeable pattern).
vado resolver
As this has to happen in a browser, the actual resolver lives offchain as a single plain HTML file without any dependencies like it’s good ol’ 1999. After all, not more than 5 kB required to read from a smart contract. With no dependencies and without using any build tool, this makes the resolver easily deployable and reproducable everywhere, and for many years to come.
Within the resolver HTML file, the contract’s getUrl()
method is called with standard Web Fetch API over a random public RPC, and a redirect is performed to the resolved URL. If this fails, it will try again with a different RPC until it succeeds or gives up after 5 tries.
Any passed pathname is considered the shortcode to be resolved. When no pathname is provided, it will redirect to app.vado.link.
Additionally, vadoAddress
& chainId
can be passed as optional query parameters mainly for testing purposes, where:
vadoAddress
: the address of the vado (proxy) contract (default: contract address on Base)chainId
: the chain ID to use for the RPC (default:8453
for Base)
e.g. https://vado.link/5XE0i?vadoAddress=0x…&chainId=1337
The resolver content hash is stored in the vado
contract as resolverContentHash
for provenance and transparency. Itcan be used to verify that whatever runs under vado.link
, vado.eth.link
, vado.eth.limo
is showing the intended content:
function resolverContentHash() external view returns (string memory);
Resolving from smart contracts
Contract exposes a getter method getUrl()
which can be used to resolve a shortcode to a URL:
function getUrl(string memory code) external view returns (string memory);
vado app
- Astro application with static export, all vanilla HTML/CSS/JS with no additional frameworks
- RabbyKit for wallet connection
- wagmi/core and viem for contract interactions
Deployed under app.vado.eth
which can be accessed by either:
vado token
The vado token (VADO) is a utility token for the vado service that enables access to premium features and fee discounts for creating links.
- Total supply (fixed): 100,000,000 VADO (100 million)
- Decimals: 18
- No mint function: Fixed supply, non-inflationary
- Standard ERC20 implementation, no special functions or restrictions on transfers
- Non-upgradeable contract
- Deployed on Base network
vado subgraph
in progress for public usage
The vado subgraph provides a GraphQL API for the vado service that allows you to query the data stored in the vado contracts.
E.g. to get all active links for a user:
{
user(id: "0x...") {
links {
shortCode
url
createdAt
}
}
}
TODO: add more examples, figure out how to best allow public access to the subgraph
Domains
All domains can be used interchangeably, and will always resolve to the same service. This protects the service and therefore the short links you create from being taken down by any actor.
These domains only serve as an interface to the underlying contracts, the store of short codes to URLs can never be taken down by anyone. At the same time, everyone can create their own interface or resolver and point it to the underlying contracts.
vado.link
This is used as the default domain for the service as it provides the most concise short links for now, and provides best compatibility for crypto and non-crypto users alike. But it is also the most centralized way of accessing the vado service.
Currently, the DNS on Cloudflare is configured to point to deployments of the resolver, app, and docs on Vercel. At the same time, the vado.link
domain is an imported ENS name, so if you use a service or browser plugin that supports ENS, it will resolve to the underlying IPFS content hashes instead of the Vercel deployment.
vado.link
→ resolverapp.vado.link
→ appdocs.vado.link
→ docs
vado.eth
The ENS name for the vado service, where the underlying account is the deployer and owner of the vado contracts.
Its content hash feature is then used to point to various parts of the vado service, like the resolver and app. The root ENS name is configured to point to the resolver content hash.
Subnames are then used for other components and if you use a service or browser plugin that supports ENS, it will resolve to the underlying IPFS content hashes:
vado.eth
→ resolver content hashapp.vado.eth
→ app content hashdocs.vado.eth
→ docs content hash
vado.eth.link
in progress
This can be considered semi-decentralized, as the underlying service is controlled by a single entity.
Because vado.eth is configured with aforementioned mentioned subnames, these are mirrored here and can be used in every browser without special plugins or services:
vado.eth.link
→ resolver content hashapp.vado.eth.link
→ app content hashdocs.vado.eth.link
→ docs content hash
TODO: figure out wildcard rewrites so e.g. vado.eth.link/SHORTCODE
actually works
vado.eth.limo
in progress
This can be considered fully decentralized, as the underlying service is DAO-controlled.
Just like above, vado.eth is configured with subnames, so those are mirrored here too and can be used in every browser without special plugins or services:
vado.eth.limo
→ resolver content hashapp.vado.eth.limo
→ app content hashdocs.vado.eth.limo
→ docs content hash
TODO: figure out wildcard rewrites so e.g. vado.eth.limo/SHORTCODE
actually works
Deployments
Base
Contract | Address |
---|---|
vado proxy | 0x45ae3dAeE940e81284807f727Ca7766ea37368c6 |
vado implementation | 0xEa8f74c24b18FD89D6635195b1ED8752C218CaAA |
vado token | 0x97bb548b3ddb756771afb1903d3563f69465be8b |
Base Sepolia (Testing)
Contract | Address |
---|---|
vado proxy | 0xbc32F0cCBFBEFEeaD6FEE13A86a10263e35cc838 |
vado implementation | 0x193591884C5f8527c86e331bA907cB1A7268C8e3 |
vado token | 0x29110781d0f22f7a645ff71a490d558f23fd98b4 |
built by alatus labs